home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1997 July
/
EnigmA AMIGA RUN 20 (1997)(G.R. Edizioni)(IT)[!][issue 1997-07 & 08][EAR-CD IV].iso
/
earcd
/
biz
/
dbase
/
db3_4src.lha
/
db3.4
/
db.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-03-16
|
83KB
|
3,132 lines
/**********************************************************************/
/* Includes */
/**********************************************************************/
#include <stdio.h>
#include <time.h>
#include <dos.h> /* For getpath() */
#include <dos/stdio.h>
#include <stdlib.h> /* qsort ... */
#include <string.h>
#include <ctype.h>
#include <exec/types.h>
#include <exec/memory.h>
#include <exec/ports.h>
#include <clib/alib_protos.h> /* NewList() */
#include <intuition/intuition.h>
#include <intuition/classes.h>
#include <intuition/classusr.h>
#include <intuition/imageclass.h>
#include <intuition/gadgetclass.h>
#include <gadgets/textfield.h>
#include <workbench/workbench.h> /* For the project icon creation */
#include <workbench/startup.h> /* For the project icon start */
#include <libraries/asl.h>
#include <libraries/gadtools.h>
#include <libraries/commodities.h> /* This has a nice qualifier #define */
#include <libraries/iffparse.h>
#include <devices/serial.h> /* For dialing */
#include <datatypes/textclass.h> /* This has defines for IFF IDs */
#include <graphics/displayinfo.h>
#include <graphics/gfxbase.h>
#include <graphics/text.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/intuition.h>
#include <proto/gadtools.h>
#include <proto/iffparse.h>
#include <proto/graphics.h>
#include <proto/utility.h>
#include <proto/icon.h>
#include <proto/asl.h>
#include <proto/wb.h>
#include <proto/diskfont.h>
#include <proto/textfield.h>
#include <clib/alib_protos.h>
#include "dbGUI.h"
#include "db.h"
#include "dbparser.h"
#include "dbtexts.h"
#include "Select.h"
#include "dbRexx.h"
#include "Design.h"
#include "Version.h"
/**********************************************************************/
/* Defines */
/**********************************************************************/
#ifdef LATTICE
void __regargs __chkabort(void); /* Disable SAS CTRL/C handling */
void __regargs __chkabort(void) {} /* One may also use the nocheckabort flag */
#endif
#define MY_FILE_BUF 65536
/* Argument to DoSort() offset */
#define NORMAL_SORT -1
#define UNSORT -2
/**********************************************************************/
/* Globals */
/**********************************************************************/
char EmptyString[]="";
struct TagItem frtags[] =
{
ASLFR_InitialHeight, MYHEIGHT,
ASLFR_InitialWidth, MYWIDTH,
ASLFR_InitialLeftEdge, MYLEFTEDGE,
ASLFR_InitialTopEdge, MYTOPEDGE,
ASLFR_DoPatterns, TRUE,
ASLFR_RejectIcons, TRUE,
TAG_DONE
};
struct LocaleInfo LocaleInfo = { NULL, NULL };
struct Locale *MyLocale = NULL;
/* For correct 'Default Tool' in icons */
char ProgramDirAndName[FMSIZE];
LONG WinSig = 0; /* For IDCMP handling */
struct TextFont *UserTextFont = NULL; /* Global so OpenLayWin() can check */
/* If this font should be used */
struct Pro *FirstPro = NULL;
struct Pro *CurrentPro = NULL;
/* For ReadArgs() */
UBYTE SerialUnit = 0;
UBYTE DialSpeed = 4;
int UserFontYSize = -1; /* Illegal height defaults to screen font */
struct RDArgs *MyRDArgs = NULL; /* Shell arguments hook */
UBYTE **TTypes = NULL; /* WB ToolTypes hook */
UBYTE MyTemplate[] = "Files/M,DEVICE/K,UNIT/K/N,DIALPREFIX/K,DIALPOSTFIX/K,"
"AREACODE/K,PUBSCREEN/K,FONTNAME/K,FONTSIZE/K/N,NOICONS/S,NOSPEEDRENDER/S,"
"NORETURNSTEP/S,NOSERIAL/S,HORIZBAR/S,ESCQUIT/S,TONEDIAL/S,"
"TONEDIALSPEED/K/N,CCITT5/S,MAKEBACKUP/S,LOCALESORT/S,HIGHLABEL/S,NOBORDER/S";
LONG MyArgArray[] = {
NULL,
(LONG)"serial.device",
(LONG)&SerialUnit,
(LONG)"ATDT ",
(LONG)";H\r",
(LONG)"",
(LONG) NULL,
(LONG)"",
(LONG)&UserFontYSize,
FALSE,
FALSE,
FALSE,
FALSE,
FALSE,
FALSE,
FALSE,
(LONG)&DialSpeed,
FALSE,
FALSE,
FALSE,
FALSE,
FALSE
};
/* Global Prefs settings.. */
BOOL DisplayWarnings = TRUE;
/* sorting stuff */
BOOL AutoSort = FALSE;
typedef int (*CompFunc)(char *, char *);
struct SortOrder {
short Order;
short Offset;
CompFunc CmpFunc; /* numeric fieldtypes require other sort functions */
};
struct SortInfo {
struct SortOrder *so;
size_t norders;
char SortDir;
BOOL UnSort; /* Sort the database based upon each record's address instead */
} SI = { NULL, 0, SORT_DIR_AZ, FALSE };
/* AppWindow specifics */
struct MsgPort *AWPort = NULL;
/* End of AppWindow specifics */
/* Security variables */
char UserName[50] = "«No keyfile needed»";
int UserID = 0;
/* For the serial device used in dialing*/
struct MsgPort *SerialMP = NULL;
struct IOExtSer *SerialIO = NULL;
/* For the clipboard */
struct IFFHandle *Iff0 = NULL, *Iff1 = NULL;
BOOL PassWordOk = TRUE; /* Security */
struct Library *RexxSysBase = NULL;
struct Library *LocaleBase = NULL;
struct Library *DiskfontBase = NULL;
struct Library *IFFParseBase = NULL;
struct Library *IconBase = NULL;
struct Library *CxBase = NULL;
struct Library *AslBase = NULL;
struct GfxBase *GfxBase = NULL;
struct IntuitionBase *IntuitionBase = NULL;
struct Library *GadToolsBase = NULL;
struct Library *UtilityBase = NULL;
struct Library *WorkbenchBase = NULL; /* For AppWindow */
struct Library *TextFieldBase = NULL;
Class *TextFieldClass = NULL;
/**********************************************************************/
/* Prototypes */
/**********************************************************************/
/**********************************************************************/
/* Functions */
/**********************************************************************/
LONG EasyLocRequest(struct Window *w, struct EasyStruct *es, ULONG *idcmp,
APTR arg1, ...)
{
/* Displays an EasyRequest where the strings are locale string-indexes */
LONG ret_val;
struct EasyStruct nes;
nes.es_StructSize = sizeof(struct EasyStruct);
nes.es_Flags = 0;
nes.es_Title = GetAppStr((LONG)es->es_Title);
nes.es_TextFormat = GetAppStr((LONG)es->es_TextFormat);
nes.es_GadgetFormat = GetAppStr((LONG)es->es_GadgetFormat);
if (w) BlockInput(w, TRUE);
ret_val = EasyRequestArgs(w, &nes, idcmp, &arg1);
if (w) FreeInput(w);
return ret_val;
}
void ShowError(int errnum, char *text)
{
struct Window *w;
if (errnum >= 0) return;
if (CurrentPro->CurrentLayout) w = CurrentPro->CurrentLayout->Window;
switch (errnum) {
case MEM_ERR:
EasyLocRequest(w, &ES_MemWarn, NULL, text);
break;
case RFF_ERR:
EasyLocRequest(w, &ES_MangledRFF, NULL, text);
break;
case FILE_ERR:
EasyLocRequest(w, &ES_WrongFileType, NULL, text);
break;
case GAD_ERR:
case WIN_ERR:
case MENU_ERR:
EasyLocRequest(w, &ES_WinOpenErr, NULL, NULL);
break;
case WINSIZE_ERR:
EasyLocRequest(w, &ES_WinSizeErr, NULL, NULL);
break;
default:
EasyLocRequest(w, &ES_DefaultErr, NULL, NULL);
break;
}
}
BOOL JumpList(struct Pro *Pr, int delta)
{
int newnum = Pr->RecNum+delta;
struct Rec *rp = Pr->CurrentRec;
if (newnum >= Pr->RecSum || newnum < 0) return FALSE; /* Outside */
Pr->RecNum = newnum; /* First correct the record number */
if (delta>0) while (delta) { rp=rp->Next; delta--; }
else while (delta) { rp=rp->Prev; delta++; }
Pr->CurrentRec = rp;
return TRUE;
}
Field GetFld(struct Rec *crp, short Offset)
{
if (!crp->Fields || Offset >= crp->FldSum) return EmptyString;
return crp->Fields[Offset];
}
/* Functions to support reading and updating arbitrary fieldtypes */
unsigned char *convertLF(unsigned char *s)
{
unsigned char *start;
for (start = s; *s; s++) {
if (*s == '\n') *s = 0xb6; /* The paragraph character */
else if (*s == 0xb6) *s = '\n';
}
return s;
}
char *ReadVisFld(struct Pro *Pr, struct VisFldInfo *vf)
/* CheckBox and CycleGadgets that are disabled return empty string */
{
// static char returnstring[10]; /* All VisFld's shall return strings */
static char returnstring[10000]; /* All VisFld's shall return strings */
char *s;
ULONG size;
if (!vf) return EmptyString; /* Safety */
switch (vf->Gadget->GadgetID) {
case STRING_KIND :
return (char *)GetStr(vf->Gadget);
break;
case TEXT_KIND :
return GetFld(*Pr->Recpp, vf->Offset);
break;
case CHECKBOX_KIND :
case CYCLE_KIND :
if (vf->Gadget->Flags & GFLG_DISABLED) return EmptyString;
stci_d(returnstring, vf->Code);
return returnstring;
break;
case TEXTFIELD_KIND :
OffGadget(vf->Gadget, Pr->CurrentLayout->Window, NULL);
GetAttr(TEXTFIELD_Size, vf->Gadget, (ULONG *)&size);
GetAttr(TEXTFIELD_Text, vf->Gadget, (ULONG *)&s);
OnGadget(vf->Gadget, Pr->CurrentLayout->Window, NULL);
if (size) {
stccpy(returnstring, s, size+1);
convertLF(returnstring);
return returnstring;
} else return EmptyString;
break;
}
}
char *CodeToText(struct VisFldInfo *vf, char *s)
/* For vf:s of string kind, returns s */
/* For vf:s of checkbox returns space or X */
/* For vf:s of cycle kind returns full text */
/* CheckBox and CycleGadgets that are disabled return empty string */
{
static char returnstring[3]; /* All VisFld's shall return strings */
int x;
if (!(vf && s)) return s;
switch (vf->Gadget->GadgetID) {
case STRING_KIND :
case TEXT_KIND :
case TEXTFIELD_KIND :
return s;
break;
}
stcd_i(s, &x);
switch (vf->Gadget->GadgetID) {
case CHECKBOX_KIND :
returnstring[0]=' ';
returnstring[1]='\0';
if (x) returnstring[0] = 'X';
return returnstring;
break;
case CYCLE_KIND :
returnstring[0] = '\0';
if (vf->Gadget->Flags & GFLG_DISABLED) return returnstring;
return vf->CEnt[x % vf->NEnt]; /* % is for safety */
break;
}
}
void WriteVisFld(struct VisFldInfo *vf, struct Window *Win, char *s)
/* Only updates CheckBox and Cyclegadgets if a change has been made */
{
int NewCode;
if (!s) s = EmptyString;
switch (vf->Gadget->GadgetID) {
case STRING_KIND :
GT_SetGadgetAttrs(vf->Gadget,Win,NULL, GTST_String, s,TAG_DONE);
break;
case TEXT_KIND :
GT_SetGadgetAttrs(vf->Gadget,Win,NULL, GTTX_Text, s, TAG_DONE);
break;
case TEXTFIELD_KIND :
convertLF(s);
SetGadgetAttrs(vf->Gadget,Win,NULL, TEXTFIELD_Text, s, TAG_DONE); /* NOT GT_ */
convertLF(s);
break;
default :
stcd_i(s, &NewCode);
if (NewCode != vf->Code) {
vf->Code = NewCode;
switch (vf->Gadget->GadgetID) {
case CHECKBOX_KIND :
GT_SetGadgetAttrs(vf->Gadget,Win,NULL,
GTCB_Checked, NewCode, TAG_DONE);
break;
case CYCLE_KIND :
GT_SetGadgetAttrs(vf->Gadget,Win,NULL,
GTCY_Active, NewCode, TAG_DONE);
break;
}
}
break;
}
}
__inline char *MyStrCpy(char *dest, char *src)
{
while(*dest++ = *src++);
return dest;
}
__inline int QuickLen(struct Rec *crp, short offset)
{
return crp->Fields[offset+1] - crp->Fields[offset] - 1;
}
BOOL UpdateFld(struct Rec *crp, short offset, char *s)
{
/* Return TRUE if some change has been made */
Field *nl, *ol = crp->Fields;
Field next, oldfld, olddata = NULL;
int i, len, diff, size, oldsize = 0;
/* Is an update necessary? */
if (!strcmp(s, GetFld(crp, offset))) return FALSE;
/* Ok, lets do the tedious update now */
len = strlen(s);
if (ol) {
olddata = ol[0];
oldsize = ol[crp->FldSum]-ol[0];
}
diff = offset - (crp->FldSum-1);
if (diff > 0) { /* expand list. i.e. create a new one */
size = oldsize + diff + len; /* (diff-1) + (len+1) */
if (!(nl = AllocMem((2+offset)*sizeof(Field), 0))) return FALSE;
if (!(nl[0] = AllocMem(size, 0))) {
FreeMem(nl, (2+offset)*sizeof(Field));
return FALSE;
}
/* Copy data */
for (i=0; i < crp->FldSum; i++) {
nl[i+1] = MyStrCpy(nl[i], ol[i]); /* MyStrCpy returns address after end of dest. */
}
for (; i < offset; i++) {
nl[i+1] = MyStrCpy(nl[i], EmptyString);
}
nl[i+1] = MyStrCpy(nl[i], s);
/* Clean up */
if (ol) FreeMem(ol, (1+crp->FldSum)*sizeof(Field));
crp->Fields = nl;
crp->FldSum = offset+1;
}
else { /* Reuse old list (there is always an old list here) */
size = oldsize - (ol[offset+1]-ol[offset]) + len+1;
if (!(ol[0] = AllocMem(size, 0))) { ol[0] = olddata; return FALSE; }
/* Copy data */
for (i=0, oldfld = olddata; i < crp->FldSum; i++) {
if (i == offset) next = MyStrCpy(ol[i], s);
else next = MyStrCpy(ol[i], oldfld);
oldfld = ol[i+1];
ol[i+1] = next;
}
}
if (olddata) FreeMem(olddata, oldsize); /* Clean up */
return TRUE;
}
void UpdateRecord(struct Pro *Pr)
{
BOOL mod = FALSE;
struct Rec *crp = *Pr->Recpp;
struct VisFldInfo *vf = Pr->CurrentLayout->FirstVisFldInfo;
char *s;
if (Pr->Quiet || !(Pr->Modified & RECMODIFIED)) return;
for (; vf; vf = vf->Next) {
s = ReadVisFld(Pr, vf);
if (UpdateFld(crp, vf->Offset, s)) mod = TRUE;
}
Pr->Modified &= ~RECMODIFIED;
if (mod && (Pr->CurrentRec == crp)) Pr->Modified |= PROMODIFIED;
}
void UpdateTitleBar(struct Pro *Pr, char *InfoTxt)
{
if (Pr->Quiet) return;
if (InfoTxt) {
sprintf(Pr->CurrentLayout->Title,"%s", InfoTxt);
}
else {
if (Pr->Modified & PROMODIFIED) { /* File modified */
sprintf(Pr->CurrentLayout->Title,"* %s/%s %5d/%d",
Pr->Name,Pr->CurrentLayout->Name,Pr->RecNum+1,Pr->RecSum);
} else {
sprintf(Pr->CurrentLayout->Title," %s/%s %5d/%d",
Pr->Name,Pr->CurrentLayout->Name,Pr->RecNum+1,Pr->RecSum);
}
}
SetWindowTitles(Pr->CurrentLayout->Window,Pr->CurrentLayout->Title,(UBYTE *)-1);
}
void UpdateDragBar(struct Pro *Pr)
{
if (Pr->Quiet) return;
GT_SetGadgetAttrs(Pr->CurrentLayout->DragGad,Pr->CurrentLayout->Window, NULL,
GTSC_Total, Pr->RecSum+1,
GTSC_Top, Pr->RecNum, TAG_DONE);
}
void MyActivateGadget(struct VisFldInfo *vf, struct Window *Win)
/* Gets called when user hits a field's corresponding key */
/* Stringgadgets gets activated, checkbox gadgets gets toggled and */
/* cyclegadgets gets cycled */
{
VisFldSelected(vf->Gadget);
switch (vf->Gadget->GadgetID) {
case STRING_KIND :
case TEXTFIELD_KIND :
ActivateGadget(vf->Gadget, Win, NULL);
break;
case CHECKBOX_KIND :
vf->Code = (vf->Code) ? 0 : 1;
GT_SetGadgetAttrs(vf->Gadget,Win,NULL,
GTCB_Checked, vf->Code, TAG_DONE);
break;
case CYCLE_KIND :
if (DB_Msg.Qualifier & IXSYM_SHIFTMASK) /* Cycle backwards */
vf->Code = (vf->Code+vf->NEnt-1) % vf->NEnt;
else vf->Code = (vf->Code+1) % vf->NEnt;
GT_SetGadgetAttrs(vf->Gadget,Win,NULL,
GTCY_Active, vf->Code, TAG_DONE);
break;
}
}
void UpdateGadgets(struct Pro *Pr)
{
UWORD pos;
struct Rec *crp = *Pr->Recpp;
struct VisFldInfo *vf = Pr->CurrentLayout->FirstVisFldInfo;
if (Pr->Quiet) return;
if (!vf) return;
if (Pr->CurrentLayout->ComplexGadgets) { /* CheckBox and Cyclegadgets */
for (; vf; vf = vf->Next)
WriteVisFld(vf, Pr->CurrentLayout->Window, GetFld(crp,vf->Offset));
}
else { /* Just Stringadgets in current view. This one is faster. */
pos = RemoveGList(Pr->CurrentLayout->Window, Pr->CurrentLayout->FirstVisFldInfo->Gadget, -1);
/* Do the update here */
for (; vf; vf = vf->Next)
strcpy(GetStr(vf->Gadget), GetFld(crp, vf->Offset));
/* Re link */
AddGList(Pr->CurrentLayout->Window, Pr->CurrentLayout->FirstVisFldInfo->Gadget, pos, -1, NULL);
RefreshGList(Pr->CurrentLayout->FirstVisFldInfo->Gadget, Pr->CurrentLayout->Window, NULL, -1);
}
if (MyRexxPort && (Pr->Mode == MODE_NORMAL)) { /* Run rexx scripts when a new record appears */
struct RFFTag *rxtag;
BOOL success = FALSE;
if (rxtag = SearchTags(CurrentPro, NULL, NULL, NEWRECORDRXFILE, NEWRECORDRXSTRING))
if (rxtag->ID == NEWRECORDRXSTRING) success = SendRexxStrCommand(rxtag->Data);
else success = SendRexxCommand(rxtag->Data);
if (success) {
do WaitPort(MyRexxPort);
while (!HandleRexxMessage(MyRexxPort));
}
}
}
void UpdateWindow(struct Pro *Pr)
{
UpdateTitleBar(Pr,NULL);
UpdateGadgets(Pr);
}
BOOL CopyToClipboard(struct Pro *Pr)
{
Field fld;
struct Rec *crp = *Pr->Recpp;
struct VisFldInfo *vf = Pr->CurrentLayout->FirstVisFldInfo;
struct FldInfo *f = Pr->FirstFldInfo;
int i, len;
char normalsep[]="X", parasep[] = "\n\n", *separator = NULL;
char *s;
if (OpenIFF(Iff0, IFFF_WRITE)) return FALSE;
if (PushChunk(Iff0, ID_FTXT, ID_FORM, IFFSIZE_UNKNOWN)) {
CloseIFF(Iff0);
return FALSE;
}
if (PushChunk(Iff0, 0, ID_CHRS, IFFSIZE_UNKNOWN)) {
CloseIFF(Iff0);
return FALSE;
}
for (; vf; vf = vf->Next) {
if (separator) {
if (strlen(separator) != WriteChunkBytes(
Iff0,separator,strlen(separator))) {
CloseIFF(Iff0);
return FALSE;
}
}
if (*(fld = GetFld(crp,vf->Offset))) {
s = CodeToText(vf, fld);
len = strlen(s);
if (len != WriteChunkBytes(Iff0,s,len)) {
CloseIFF(Iff0);
return FALSE;
}
}
if ((normalsep[0] = vf->VisSep) == '\f') separator = parasep;
else separator = normalsep;
}
if (!PopChunk(Iff0)) PopChunk(Iff0);
CloseIFF(Iff0);
/* Now do unit 1 */
if (OpenIFF(Iff1, IFFF_WRITE)) return FALSE;
if (PushChunk(Iff1, ID_FTXT, ID_FORM, IFFSIZE_UNKNOWN)) {
CloseIFF(Iff1);
return FALSE;
}
if (PushChunk(Iff1, 0, ID_CHRS, IFFSIZE_UNKNOWN)) {
CloseIFF(Iff1);
return FALSE;
}
for (i=0; f; f = f->Next,i++) {
if (*(fld = GetFld(crp,i))) {
len = strlen(f->Name);
if (len != WriteChunkBytes(Iff1,f->Name,len)) {
CloseIFF(Iff1);
return FALSE;
}
if (1 != WriteChunkBytes(Iff1,"\t",1)) {
CloseIFF(Iff1);
return FALSE;
}
len = strlen(fld);
if (len != WriteChunkBytes(Iff1,fld,len)) {
CloseIFF(Iff1);
return FALSE;
}
if (1 != WriteChunkBytes(Iff1,"\n",1)) {
CloseIFF(Iff1);
return FALSE;
}
}
}
if (!PopChunk(Iff1)) PopChunk(Iff1);
CloseIFF(Iff1);
return TRUE;
}
BOOL ClipToRec(struct Pro *Pr, struct Rec *crp, char *clipbuf)
{
struct FldInfo *f;
short offset;
char *p;
BOOL retval = FALSE, found;
while (*clipbuf) {
found = FALSE;
if (!(p = strpbrk(clipbuf,"\t"))) break;
*p = '\0';
for (offset = 0,f = Pr->FirstFldInfo; f; offset++, f = f->Next) {
if (!(Stricmp(f->Name,clipbuf))) {
found = TRUE;
clipbuf = p+1; /* Move to data */
if (!(p = strpbrk(clipbuf,"\n"))) return FALSE;
*p = '\0';
UpdateFld(crp, offset, clipbuf);
retval = TRUE;
}
}
clipbuf = p+1;
if (!found) { /* Skip unknown data */
if (!(p = strpbrk(clipbuf,"\n"))) return FALSE;
clipbuf = p+1;
}
}
return retval;
}
BOOL PasteFromClipboard(struct Pro *Pr, struct Rec *crp)
{
struct ContextNode *cn;
UBYTE *buf;
BOOL retval = FALSE;
long error, rlen;
if (!(buf = AllocMem(LOADBUFFERSIZE*10,0))) return FALSE;
/* if (Iff1 = AllocIFF()) {
if (Iff1->IFF_Stream = (ULONG) OpenClipboard(1)) {
InitIFFasClip(Iff1); */
if (!OpenIFF(Iff1, IFFF_READ)) {
/* Stop on CHRS chunks */
if (!StopChunk(Iff1, ID_FTXT, ID_CHRS)) {
/* Find all FTXT CHRS chunks */
while (1) {
error = ParseIFF(Iff1, IFFPARSE_SCAN);
if (error == IFFERR_EOC) continue; /* End of context */
else if (error) break;
cn = CurrentChunk(Iff1);
if((cn)&&(cn->cn_Type == ID_FTXT)&&(cn->cn_ID == ID_CHRS)) {
while((rlen = ReadChunkBytes(Iff1,buf,LOADBUFFERSIZE-1)) > 0) {
buf[rlen] = (UBYTE)'\0'; /* ReadChunkBytes won't do this */
retval = ClipToRec(Pr,crp, buf);
}
if(rlen < 0) error = rlen;
}
} /* while */
if((error)&&(error != IFFERR_EOF)) retval = FALSE;
} /* StopChunk */
CloseIFF(Iff1);
} /* OpenIFF */
/* CloseClipboard((struct ClipboardHandle *)Iff1->IFF_Stream);
} /* OpenClipboard */
FreeIFF(Iff1);
} /* AllocIFF */
*/ FreeMem(buf,LOADBUFFERSIZE*10);
return retval;
}
void DisableComplex(struct Layout *Lay, BOOL disable)
/* Disables/enables complex gadgets, ie checkbox and cyclegadgets in a view */
{
struct VisFldInfo *vf = Lay->FirstVisFldInfo;
for (; vf; vf = vf->Next) {
if ((vf->Gadget->GadgetID == CHECKBOX_KIND) ||
(vf->Gadget->GadgetID == CYCLE_KIND))
GT_SetGadgetAttrs(vf->Gadget,Lay->Window,NULL,
GA_Disabled, disable, TAG_DONE);
}
}
void SetProMode(struct Pro *Pr, char Mode)
/* Sets the mode and corrects the menus and gadgets */
/* Old data in gadgets has to be saved prior to calling this function */
{
// if (Pr->Mode == Mode) return; /* Already this mode */
if (!(Pr->CurrentLayout && Pr->CurrentLayout->Window)) return;
if (!Pr->Quiet) UpdateRecord(Pr);
Pr->Mode = Mode;
switch (Mode) { /* New mode */
case MODE_NORMAL:
Pr->Recpp = &Pr->CurrentRec;
if (Pr->Quiet) break;
OnMenu(Pr->CurrentLayout->Window, FULLMENUNUM(0,NOITEM,NOSUB)); /* Project */
OnMenu(Pr->CurrentLayout->Window, FULLMENUNUM(1,4,NOSUB)); /* Edit->Add */
OnMenu(Pr->CurrentLayout->Window, FULLMENUNUM(3,5,NOSUB)); /* Action->Browse */
OnMenu(Pr->CurrentLayout->Window, FULLMENUNUM(2,NOITEM,NOSUB)); /* Action */
DisableComplex(Pr->CurrentLayout, FALSE);
UpdateWindow(Pr);
UpdateDragBar(Pr);
break;
case MODE_FIND:
Pr->Recpp = &Pr->FindRec;
if (Pr->Quiet) break;
OffMenu(Pr->CurrentLayout->Window, FULLMENUNUM(0,NOITEM,NOSUB)); /* Project */
OffMenu(Pr->CurrentLayout->Window, FULLMENUNUM(1,4,NOSUB)); /* Edit->Add */
OffMenu(Pr->CurrentLayout->Window, FULLMENUNUM(3,5,NOSUB)); /* Action->Browse */
OffMenu(Pr->CurrentLayout->Window, FULLMENUNUM(2,NOITEM,NOSUB)); /* Action */
UpdateTitleBar(Pr, GetAppStr(MSG_FIND_MODE_WINMSG));
GT_SetGadgetAttrs(Pr->CurrentLayout->DragGad,
Pr->CurrentLayout->Window, NULL,
GTSC_Total, 2,
GTSC_Top, 0, TAG_DONE);
DisableComplex(Pr->CurrentLayout, TRUE);
UpdateGadgets(Pr);
break;
case MODE_SORT:
Pr->Recpp = &Pr->SortRec;
if (Pr->Quiet) break;
OffMenu(Pr->CurrentLayout->Window, FULLMENUNUM(0,NOITEM,NOSUB)); /* Project */
OffMenu(Pr->CurrentLayout->Window, FULLMENUNUM(1,4,NOSUB)); /* Edit->Add */
OffMenu(Pr->CurrentLayout->Window, FULLMENUNUM(3,5,NOSUB)); /* Action->Browse */
OffMenu(Pr->CurrentLayout->Window, FULLMENUNUM(2,NOITEM,NOSUB)); /* Action */
UpdateTitleBar(Pr, GetAppStr(MSG_SORT_MODE_WINMSG));
GT_SetGadgetAttrs(Pr->CurrentLayout->DragGad,
Pr->CurrentLayout->Window, NULL,
GTSC_Total, 2,
GTSC_Top, 0, TAG_DONE);
DisableComplex(Pr->CurrentLayout, TRUE);
UpdateGadgets(Pr);
break;
}
/**/ if (ReactivateGad)
ActivateGadget(LastGad, CurrentPro->CurrentLayout->Window, NULL);
}
__inline void ClearRecord(struct Rec *crp)
{
if (!crp->Fields) return;
FreeMem(crp->Fields[0], crp->Fields[crp->FldSum] - crp->Fields[0]);
FreeMem(crp->Fields, (1+crp->FldSum)*sizeof(Field));
crp->Fields = NULL;
crp->FldSum = 0;
}
struct Rec *NewRecord(void)
{
struct Rec *rp;
if (!(rp = (struct Rec *) AllocMem(sizeof(struct Rec),0))) return NULL;
/* Initialize the data */
rp->Prev = rp->Next = NULL;
rp->Fields = NULL;
rp->FldSum = 0;
}
struct Rec *AddRecord(struct Rec **crpp) /* Pointer to pointer to curr rec */
{
/* Unfortunately this function also creates a record */
struct Rec *rp = NewRecord();
if (!rp) return NULL;
if (*crpp) {
rp->Next = (*crpp)->Next; /* Curr New->Next */
(*crpp)->Next = rp; /* Curr->New Next */
rp->Prev = *crpp; /* Curr<-New Next */
if (rp->Next) rp->Next->Prev = rp; /* Curr New<-Next */
}
else { /* First record */
rp->Next = NULL;
rp->Prev = NULL;
*crpp = rp;
}
return rp;
}
void DeleteRecord(struct Rec **crpp)
{
struct Rec *rp = *crpp;
ClearRecord(*crpp);
if (rp->Next) *crpp = rp->Next; /* Prev Curr >Next */
else if (rp->Prev) *crpp = rp->Prev; /* Prev< Curr Next */
else *crpp = NULL; /* Empty list */
/* unlink it */
if (rp->Prev) rp->Prev->Next = rp->Next; /* Prev -> Next */
if (rp->Next) rp->Next->Prev = rp->Prev; /* Prev <- Next */
FreeMem(rp,sizeof(struct Rec));
}
BOOL KillRecord(struct Pro *Pr)
/* Does some checking, handles RecNum and RecSum and calls DeleteRecord */
{
if (Pr->RecSum > 1) {
Pr->RecSum--;
if (Pr->RecNum >= Pr->RecSum)
Pr->RecNum--;
DeleteRecord(&Pr->CurrentRec);
return TRUE;
}
return FALSE;
}
BOOL Match(struct Rec *Rec, struct Rec *T, struct Rec *TokenRec)
{
short offset;
Field fld, tfld, tokf;
for (offset = 0; offset < T->FldSum; offset++) {
if (*(tfld = GetFld(T, offset))) { /* There is a pattern */
fld = GetFld(Rec,offset);
if (*(tokf = GetFld(TokenRec, offset))) { /* Check if AmigaDOS match */
if (!MatchPatternNoCase(tokf, fld)) return FALSE;
}
else if (Strnicmp(fld, tfld, QuickLen(T, offset))) return FALSE;
}
}
return TRUE;
}
struct Rec *BuildTokenRec(struct Rec *FindRec)
{
struct Rec *tokenrec = NewRecord();
Field f, tmp;
short offset, tmpsize;
if (!tokenrec) return NULL;
for (offset = FindRec->FldSum-1; offset >= 0; offset--) { /* efficient UpdateFld */
if (*(f = GetFld(FindRec, offset))) {
tmpsize = strlen(f)*2+10; /* Enough according to autodocs */
if (!(tmp = AllocMem(tmpsize, 0))) break;
if (ParsePatternNoCase(f, tmp, tmpsize)) /* WildCards exist */
UpdateFld(tokenrec, offset, tmp);
FreeMem(tmp, tmpsize);
}
}
return tokenrec;
}
struct Rec *FindRecord(struct Pro *Pr, int StartRec, int Dir)
{
int TmpRecNum;
struct Rec *TmpCurrentRec, *tokenrec;
if (StartRec >= Pr->RecSum) { /* Out of bounds */
if (!Pr->Quiet) DisplayBeep(Scr);
return NULL;
}
TmpRecNum = Pr->RecNum;
TmpCurrentRec = Pr->CurrentRec;
UpdateRecord(Pr);
/* Build a tokenrec for MatchPatternNoCase() */
if (!(tokenrec = BuildTokenRec(Pr->FindRec))) return NULL;
JumpList(Pr,-Pr->RecNum+StartRec);
do {
if (Match(Pr->CurrentRec,Pr->FindRec,tokenrec)) {
DeleteRecord(&tokenrec);
SetProMode(Pr,MODE_NORMAL);
return Pr->CurrentRec;
}
} while (JumpList(Pr,Dir));
/* No match */
/* First free the tokenrec */
DeleteRecord(&tokenrec);
if (!Pr->Quiet) DisplayBeep(Scr);
Pr->RecNum = TmpRecNum;
Pr->CurrentRec = TmpCurrentRec;
return NULL;
}
BOOL LoadRecord(BPTR fp, char *buf, struct Pro *Pr, struct Rec *crp)
{
/* The contents in this function takes more than 7/8 of the loading time to execute */
/* Conclusion: Load the whole database in one chunk using AmigaDOS functions! */
int i = 0; /* d */
register char *bp = buf;
if (!FGets(fp, buf, LOADBUFFERSIZE-1)) return FALSE; /* -1 is a v36 safety */
for (bp = buf; *bp; bp++) if (*bp == '\t') crp->FldSum++;
if (bp > buf && bp[-1] == '\n') *--bp = '\0';
if (bp == buf) return TRUE;
crp->FldSum++;
/* From here to the end of this function takes 1/8 of the loading time */
if (!(crp->Fields = AllocMem((crp->FldSum+1)*sizeof(Field), 0))) return FALSE;
if (!(crp->Fields[0] = AllocMem(bp-buf+1, 0))) {
FreeMem(crp->Fields, (crp->FldSum+1)*sizeof(Field));
crp->Fields = NULL;
return FALSE;
}
for (bp = crp->Fields[0]; *bp = *buf; bp++, buf++) {
if (*bp == '\t') {
*bp = '\0';
crp->Fields[++i] = bp+1;
}
}
crp->Fields[++i] = bp+1;
return TRUE;
}
BOOL Save1stLine(struct Pro *Pr, BPTR fp, char SaveMode)
{
struct FldInfo *f;
char separator = '\0';
for (f = Pr->FirstFldInfo; f; f=f->Next) {
if(!separator) {
if (SaveMode == SAVE_COMMA_ASCII) separator = ',';
else separator = '\t';
}
else if (FPutC(fp, separator) == EOF) return FALSE;
if (SaveMode == SAVE_COMMA_ASCII) if (FPutC(fp, '\"') == EOF) return FALSE;
if (FPuts(fp, f->Name) == EOF) return FALSE;
if (SaveMode == SAVE_COMMA_ASCII) if (FPutC(fp, '\"') == EOF) return FALSE;
}
if (FPutC(fp, '\n') == EOF) return FALSE;
return TRUE;
}
BOOL SaveRecord(struct Rec *crp, BPTR fp, char SaveMode)
{
Field fld;
int nsepa = 0;
int i;
BOOL empty = TRUE;
if (SaveMode == SAVE_COMMA_ASCII) {
for (i = 0; i < crp->FldSum; i++) {
if (*(fld = GetFld(crp, i))) {
empty = FALSE;
while (nsepa--) if (FPutC(fp, ',') == EOF) return FALSE;
if (FPutC(fp, '\"') == EOF) return FALSE;
if (FPuts(fp, fld) == EOF) return FALSE;
if (FPutC(fp, '\"') == EOF) return FALSE;
nsepa = 0;
}
nsepa++;
}
}
else {
for (i = 0; i < crp->FldSum; i++) {
if (*(fld = GetFld(crp, i))) {
empty = FALSE;
while (nsepa--) if (FPutC(fp, '\t') == EOF) return FALSE;
if (FPuts(fp, fld) == EOF) return FALSE;
nsepa = 0;
}
nsepa++;
}
}
if (!empty && FPutC(fp, '\n') == EOF) return FALSE;
return TRUE;
}
BOOL SaveView(struct Pro *Pr, struct Rec *crp, BPTR fp, BOOL names)
{
char buffer[FIELDNAMELENGTH];
char *bufp, *namep, *s;
Field fld;
struct VisFldInfo *vf = Pr->CurrentLayout->FirstVisFldInfo;
for (; vf; vf = vf->Next) {
if (names) {
/* Strip underscore _ in gadetname for correct length */
for (bufp = buffer, namep = vf->Name;; namep++) {
if (*namep != '_') *bufp++ = *namep;
if (!(*namep)) break; /* Also copy the \0 char */
}
if (FPuts(fp, buffer) == EOF) return FALSE;
if (FPuts(fp, ": ") == EOF) return FALSE;
}
if (*(fld = GetFld(crp,vf->Offset))) {
s = CodeToText(vf, fld);
if (FPuts(fp, s) == EOF) return FALSE;
}
if (vf->VisSep == '\f') {
if (FPutC(fp, '\n') == EOF) return FALSE;
if (FPutC(fp, '\n') == EOF) return FALSE;
}
else if (FPutC(fp, vf->VisSep) == EOF) return FALSE;
}
return TRUE;
}
BOOL ClearPro(struct Pro *Pr)
{
/* First delete old data */
JumpList(Pr,Pr->RecSum-Pr->RecNum-1); /* Jump to last record for speed */
while (Pr->RecSum--) DeleteRecord(&Pr->CurrentRec);
Pr->RecNum = 0;
Pr->RecSum = 0; /* No risk that RecSum gets -1 */
/* Add one record */
if (!AddRecord(&Pr->CurrentRec)) return FALSE;
Pr->RecSum++;
/* We really don't use FirstRec, but we initialize it anyway */
Pr->FirstRec = Pr->CurrentRec;
/* This also updates the window with empty fields */
SetProMode(Pr,MODE_NORMAL);
return TRUE;
}
void DeleteLayout(struct Pro *Pr, struct Layout *Lay)
{
struct RFFTag *ot;
struct VisFldInfo *vf, *nextvf;
if (!Lay) return; /* Safety */
if (Lay->Browser) DeleteSelect(Lay->Browser);
CloseLayWin(Pr, Lay);
for (vf = Lay->FirstVisFldInfo; vf; vf=nextvf) {
nextvf = vf->Next;
DeleteVisFldInfo(vf);
}
Lay->FirstVisFldInfo = NULL;
while (ot = (struct RFFTag *)RemHead((struct List *)&Lay->LayTags))
DeleteTag(ot);
FreeMem(Lay, sizeof(struct Layout));
}
struct Layout *NewLayout(struct Pro *Pr)
{
struct Layout *Lay, *l;
if (!(Lay = AllocMem(sizeof(struct Layout), MEMF_CLEAR))) return NULL;
NewList((struct List *)&Lay->LayTags);
strcpy(Lay->Name,Pr->Name); /* Same name initially */
Lay->ComplexGadgets = FALSE; /* Faster redraw routines without checkbox */
/* and cyclegadgets */
Lay->XPos = Lay->YPos = -1; /* Let db think */
/* Add this struct to the list */
if (!(l = Pr->FirstLayout)) Pr->FirstLayout = Lay;
else {
while (l->NextLayout) l = l->NextLayout;
l->NextLayout = Lay;
}
/* Browser stuff */
Lay->Browser = NewSelect();
Pr->CurrentLayout = Lay;
return Lay;
}
void DeletePro(struct Pro *Pr)
{
struct FldInfo *f, *old;
struct RxInfo *ri, *oldri;
struct RFFTag *ot;
struct RFFLine *oline;
struct Layout *l,*nextl;
if (!Pr) return; /* Safety */
/* Jumping to last record actually improves de-alloc speed a lot */
/* as this is the reverse order that the records where allocated */
JumpList(Pr,Pr->RecSum-Pr->RecNum-1); /* Jump to last record */
while (Pr->RecSum--) DeleteRecord(&Pr->CurrentRec);
if (Pr->FindRec) DeleteRecord(&Pr->FindRec);
if (Pr->SortRec) DeleteRecord(&Pr->SortRec);
ri = Pr->FirstRxInfo;
while (ri) {
while (ot = (struct RFFTag *)RemHead((struct List *)&ri->RxTags))
DeleteTag(ot);
oldri = ri; ri = ri->Next;
FreeMem(oldri, sizeof(struct RxInfo));
}
Pr->FirstRxInfo = NULL;
f = Pr->FirstFldInfo;
while (f) {
while (ot = (struct RFFTag *)RemHead((struct List *)&f->FldTags))
DeleteTag(ot);
old = f; f = f->Next;
FreeMem(old,sizeof(struct FldInfo));
}
Pr->FirstFldInfo = NULL;
while (ot = (struct RFFTag *)RemHead((struct List *)&Pr->ProTags))
DeleteTag(ot);
while (oline = (struct RFFLine *)RemHead((struct List *)&Pr->UnknownLines))
DeleteRFFLine(oline);
for (l = Pr->FirstLayout; l;) {
nextl = l->NextLayout;
DeleteLayout(Pr, l);
l = nextl;
}
Pr->FirstLayout = NULL;
CloseMenu(Pr);
FreeMem(Pr, sizeof(struct Pro));
}
struct Pro *NewPro(void)
{
struct Pro *Pr;
if (!(Pr = AllocMem(sizeof(struct Pro), MEMF_CLEAR))) return NULL;
NewList((struct List *)&Pr->ProTags);
NewList((struct List *)&Pr->UnknownLines);
strcpy(Pr->Name, GetAppStr(MSG_UNTITLED_PRO));
Pr->Mode = MODE_NORMAL;
Pr->Sep = '\t';
Pr->Modified = NOTMODIFIED;
Pr->Quiet = FALSE;
Pr->Recpp = &Pr->CurrentRec;
/* Add one FindRec and SortRec */
if (!AddRecord(&Pr->FindRec)) {
DeletePro(Pr);
return NULL;
}
if (!AddRecord(&Pr->SortRec)) {
DeletePro(Pr);
return NULL;
}
if (!ClearPro(Pr)) { /* Just to add one default record */
DeletePro(Pr);
return NULL;
}
return Pr;
}
void SwapSwed(struct Rec *crp)
{
/* Correct the order of the swedish åäö characters */
/* Uses the global struct SI (SortInfo) to determine which fields to manipulate */
int i;
Field fld;
signed char *p; /* To be explicit */
for (i=0; i<SI.norders; i++) {
if (*(fld = GetFld(crp,SI.so[i].Offset))) {
for (p = fld; *p; p++) {
if (*p & 0x80)
switch (*p) {
case 'Å': *p = 'Ä'; break;
case 'Ä': *p = 'Å'; break;
case 'å': *p = 'ä'; break;
case 'ä': *p = 'å'; break;
}
}
}
}
}
int CompareRec(struct Rec **rpp1, struct Rec **rpp2)
{
/* This function is used by qsort() to compare records. It returns values like */
/* strcmp(). It uses the global struct SI (SortInfo) to determine details like */
/* the sort order and which fields to sort on. */
int i;
Field fld1,fld2;
LONG res;
if (SI.UnSort) return *rpp1 - *rpp2;
for (i=0; i<SI.norders; i++) {
fld1 = GetFld(*rpp1,SI.so[i].Offset);
fld2 = GetFld(*rpp2,SI.so[i].Offset);
res = SI.so[i].CmpFunc(fld1, fld2);
if (res) return (SI.SortDir) ? -res : res;
}
return 0;
}
int LocaleCmp(char *str1, char *str2)
{
/* Frontend for the locale.library StrnCmp() string compare function. */
return StrnCmp(MyLocale, str1, str2, -1, SC_COLLATE2);
}
int StringCmp(char *str1, char *str2)
{
/* Frontend as one can't take the address of a dynamically linked function */
return Stricmp(str1, str2);
}
int IntegerCmp(char *str1, char *str2)
{
return atoi(str1) - atoi(str2);
}
int SortOrderCmp(struct SortOrder *sop1, struct SortOrder *sop2)
{
return sop1->Order - sop2->Order;
}
CompFunc DecideCmpFunc(struct Pro *Pr, short offset)
{
struct FldInfo *fi = GetFldInfo(Pr, offset);
struct RFFTag *tag;
if (!fi) return StringCmp; /* Safety, should never happen */
tag = FindTag(&fi->FldTags, FTYP);
if (tag && !Stricmp(tag->Data,"integer")) return IntegerCmp;
else if (MyLocale) return LocaleCmp;
else return StringCmp;
}
void DoSort(struct Pro *Pr, short offset)
{
/* If offset is non-negative, sort on it instead of using what is entered in */
/* the visual fields. (The Browser uses it to do an AutoSort) */
int i, offs, temp;
struct Rec *trec = Pr->CurrentRec;
struct Rec **recArray;
if (Pr->RecSum < 2) return;
/* Init SI */
SI.norders = 0;
if (offset >= 0) {
SI.norders = 1;
if (!(SI.so = AllocMem(sizeof(struct SortOrder),0))) {
SetProMode(Pr,MODE_NORMAL);
return; /* Out of memory */
}
SI.so->Order = 1; /* Safety */
SI.so->Offset = offset;
SI.so->CmpFunc = DecideCmpFunc(Pr, offset);
}
else if (offset == NORMAL_SORT) {
/* First check how many valid "orderfields" there are */
UpdateRecord(Pr);
for (offs=0; offs < Pr->SortRec->FldSum; offs++) {
if (stcd_i(GetFld(Pr->SortRec, offs), &temp)) SI.norders++;
}
if (SI.norders) {
if (!(SI.so = AllocMem(SI.norders * sizeof(struct SortOrder),0))) {
SetProMode(Pr,MODE_NORMAL);
return; /* Out of memory */
}
for (offs=i=0; offs < Pr->SortRec->FldSum; offs++) {
if (stcd_i(GetFld(Pr->SortRec, offs), &temp)) {
SI.so[i].Order = temp;
SI.so[i].Offset = offs;
SI.so[i++].CmpFunc = DecideCmpFunc(Pr, offs);
}
}
qsort(SI.so, SI.norders, sizeof(struct SortOrder), SortOrderCmp);
}
else {
SI.UnSort = TRUE; /* Perform an UNSORT */
UpdateRecord(Pr);
}
}
else SI.UnSort = TRUE; /* Perform an UNSORT */
/* Prepare an array of pointers to all records for qsort() */
if (!(recArray = AllocMem (Pr->RecSum * sizeof(struct Rec *), 0))) {
SetProMode(Pr, MODE_NORMAL);
FreeMem(SI.so, SI.norders * sizeof(struct SortOrder));
return;
}
while (trec->Prev) trec = trec->Prev; /* find start */
if (MyLocale) for (i=0; trec; trec = trec->Next, i++) recArray[i] = trec;
else for (i=0; trec; trec = trec->Next, i++) {
recArray[i] = trec;
SwapSwed(trec);
}
UpdateTitleBar(Pr,GetAppStr(MSG_SORTING_WINMSG)); /* Sorting might take some time */
BlockInput(Pr->CurrentLayout->Window,FALSE);
/**** qsort() ****/
qsort(recArray, Pr->RecSum, sizeof(struct Rec *), CompareRec);
if (SI.UnSort) {
Pr->IsSorted = FALSE;
SI.UnSort = FALSE;
}
else Pr->IsSorted = TRUE;
Pr->CurrentRec = recArray[0];
Pr->RecNum=0;
/* Repair the doubly linked list now */
recArray[0]->Prev = NULL;
for (i=0; i < Pr->RecSum-1; i++) {
recArray[i]->Next = recArray[i+1];
recArray[i+1]->Prev = recArray[i];
}
recArray[i]->Next = NULL; /* List repaired */
if (!MyLocale) for (trec = Pr->CurrentRec; trec; trec = trec->Next) SwapSwed(trec);
FreeMem(recArray, Pr->RecSum * sizeof(struct Rec *));
if (SI.norders) FreeMem(SI.so, SI.norders * sizeof(struct SortOrder));
FreeInput(Pr->CurrentLayout->Window);
SetProMode(Pr,MODE_NORMAL);
}
BOOL IsPhoneNumber(char *nr)
{
/* Checks if nr contains at least one number */
BOOL ret = FALSE;
if (!nr) return FALSE;
while (*nr) if (isdigit(*nr++)) { ret = TRUE; break; }
return ret;
}
BOOL SpeedRenderOn(struct Layout *Lay)
/* We build a linked list of SR structs */
{
struct VisFldInfo *vf = Lay->FirstVisFldInfo;
struct SR *tp, *old = NULL;
if (MyArgArray[NOSPEEDRENDER]) return TRUE; /* Break out */
for (; vf; vf = vf->Next) {
/* SpeedRender only works for stringgadgets */
if (vf->Gadget->GadgetID != STRING_KIND) continue;
if (!(tp = AllocMem(sizeof(struct SR),0))) return FALSE;
tp->GadgetRender = vf->Gadget->GadgetRender;
vf->Gadget->GadgetRender = NULL;
tp->Next = NULL;
if (!old) {
old = tp;
Lay->FirstSR = tp;
}
else {
old->Next = tp;
old = tp;
}
}
return TRUE;
}
void SpeedRenderOff(struct Layout *Lay)
{
struct VisFldInfo *vf = Lay->FirstVisFldInfo;
struct SR *tp = Lay->FirstSR, *old;
if (MyArgArray[NOSPEEDRENDER]) return; /* Break out */
for (; vf; vf = vf->Next) {
/* SpeedRender only works for stringgadgets */
if (vf->Gadget->GadgetID != STRING_KIND) continue;
vf->Gadget->GadgetRender = tp->GadgetRender;
old = tp; tp = tp->Next;
FreeMem(old,sizeof(struct SR));
}
Lay->FirstSR = NULL;
}
void CloseSerial(void)
{
/* Serial device specifics */
if (SerialIO) {
if (SerialIO->IOSer.io_Device) CloseDevice((struct IORequest *)SerialIO);
DeleteExtIO((struct IORequest *)SerialIO);
}
if (SerialMP) DeletePort(SerialMP);
SerialMP = NULL;
SerialIO = NULL;
}
/**********************************************************************/
/* Byebye() */
/**********************************************************************/
void ByeBye(void)
{
struct AppMessage *AppMsg;
/* Serial specifics */
CloseSerial();
/* Clipboard specifics */
if (Iff0) {
if (Iff0->iff_Stream)
CloseClipboard((struct ClipboardHandle *)Iff0->iff_Stream);
FreeIFF(Iff0);
}
if (Iff1) {
if (Iff1->iff_Stream)
CloseClipboard((struct ClipboardHandle *)Iff1->iff_Stream);
FreeIFF(Iff1);
}
/* Reclaim memory used by ReadArgs(). Don't access MyArgArray after this! */
if (MyRDArgs) FreeArgs(MyRDArgs);
else if (TTypes) ArgArrayDone();
if (CurrentPro->IsSorted) DoSort(CurrentPro, UNSORT); /* Speed. Let's help FreeMem() */
DeletePro(CurrentPro);
if (UserTextFont) CloseFont(UserTextFont);
CloseDownScreen(); /*GadToolBox*/
/* Make sure there are no more outstanding AppWin messages */
if (AWPort) {
while(AppMsg = (struct AppMessage *)GetMsg(AWPort))
ReplyMsg((struct Message *)AppMsg);
DeleteMsgPort(AWPort);
}
if (MyRexxPort) CloseRexxPort(MyRexxPort);
if (LocaleBase) {
if (MyLocale) CloseLocale(MyLocale);
if (LocaleInfo.li_Catalog) CloseCatalog(LocaleInfo.li_Catalog);
CloseLibrary (LocaleBase);
}
if (TextFieldBase) CloseLibrary(TextFieldBase);
if (RexxSysBase) CloseLibrary(RexxSysBase);
if (DiskfontBase) CloseLibrary(DiskfontBase);
if (IFFParseBase) CloseLibrary(IFFParseBase);
if (WorkbenchBase) CloseLibrary(WorkbenchBase);
if (IconBase) CloseLibrary(IconBase);
if (AslBase) CloseLibrary(AslBase);
if (CxBase) CloseLibrary(CxBase);
if (GadToolsBase) CloseLibrary(GadToolsBase);
if (UtilityBase) CloseLibrary(UtilityBase);
if (GfxBase) CloseLibrary((struct Library *)GfxBase);
if (IntuitionBase) CloseLibrary((struct Library *)IntuitionBase);
exit(0);
}
void HandleQuit(struct Pro *Pr)
/* This routine gets called by all quit-program routines */
{
UpdateRecord(Pr);
if (Pr->Modified & PROMODIFIED) /* File modified */
if (!EasyLocRequest(Pr->CurrentLayout->Window, &ES_QuitWarn, NULL, NULL)) return;
ByeBye();
}
BOOL PerformSave(struct Pro *Pr, BPTR fp, char SaveMode, struct Rec *tokenrec)
{
/* Called from SavePro. Performs the actual saving */
/* This function exists to simplify bail-out if an error occurs */
struct Rec *SaveRec;
BOOL names = (SaveMode == SAVE_VIEW_WN);
BOOL noview = (SaveMode != SAVE_VIEW) && (SaveMode != SAVE_VIEW_WN);
if (noview)
if(!Save1stLine(Pr, fp, SaveMode)) return FALSE;
if (SaveMode == SAVE_PRO)
if(!RFFOut(Pr, fp)) return FALSE;
/* Seek first record */
for (SaveRec = Pr->CurrentRec; SaveRec->Prev; SaveRec = SaveRec->Prev);
/* Save the records */
if (tokenrec) { /* ie filtered output */
if (noview) {
do {
if (Match(SaveRec,Pr->FindRec,tokenrec))
if (!SaveRecord(SaveRec,fp,SaveMode)) return FALSE;
} while (SaveRec = SaveRec->Next);
}
else {
do {
if (Match(SaveRec,Pr->FindRec,tokenrec))
if (!SaveView(Pr,SaveRec,fp,names)) return FALSE;
} while (SaveRec = SaveRec->Next);
}
}
else {
if (noview) {
do {
if (!SaveRecord(SaveRec,fp,SaveMode)) return FALSE;
} while (SaveRec = SaveRec->Next);
}
else {
do {
if (!SaveView(Pr,SaveRec,fp,names)) return FALSE;
} while (SaveRec = SaveRec->Next);
}
}
return TRUE;
}
BOOL MakeBackup(char *filename)
{
char bakname[FMSIZE];
strcpy(bakname, filename);
strcat(bakname, ".bak");
DeleteFile(bakname);
if (!Rename(filename, bakname)) return FALSE;
return TRUE;
}
BOOL SavePro(struct Pro *Pr, char *Drawer, char *Name, char SaveMode, BOOL Filter)
{
BPTR fp;
char filename[FMSIZE];
struct DiskObject *DO; /* For handling icons */
struct Rec *tokenrec = NULL;
strcpy(filename,Drawer);
if (!AddPart(filename,Name,FMSIZE-1)) { /* incorrect filename */
/* display error req */
return FALSE;
}
if (SaveMode == SAVE_PRO && MyArgArray[MAKEBACKUP]) MakeBackup(filename);
/* Open file */
if (!(fp = Open(filename, MODE_NEWFILE))) { /* open fail */
EasyLocRequest(Pr->CurrentLayout->Window,
&ES_OpenFail, NULL, filename);
return FALSE;
}
/* Set a large buffer for increased load speed */
SetVBuf(fp, NULL, BUF_FULL, MY_FILE_BUF);
if (SaveMode == SAVE_PRO) {
strcpy(Pr->Drawer,Drawer);
strcpy(Pr->Name,Name);
}
else {
strcpy(Pr->OutputName,Name);
strcpy(Pr->OutputDrawer,Drawer);
}
if (Filter) {
/* Build a tokenrec for MatchPatternNoCase() */
if (!(tokenrec = BuildTokenRec(Pr->FindRec))) {
Close(fp);
return FALSE;
}
}
UpdateTitleBar(Pr,GetAppStr(MSG_SAVING_WINMSG)); /* User feedback that file will be saved */
BlockInput(Pr->CurrentLayout->Window,TRUE);
UpdateRecord(Pr); /* Don't forget this! */
if (!PerformSave(Pr,fp,SaveMode, tokenrec)) {
/* Save error */
EasyLocRequest(Pr->CurrentLayout->Window,
&ES_SaveError, NULL, filename);
Close(fp);
if (tokenrec) DeleteRecord(&tokenrec);
FreeInput(Pr->CurrentLayout->Window);
UpdateTitleBar(Pr,NULL); /* Maybe a new name? */
return FALSE;
}
if (SaveMode == SAVE_PRO) {
Pr->Modified = NOTMODIFIED;
if (!MyArgArray[NOICONS]) {
/* Everything OK, Save an icon if one doesn't exist */
if (DO = GetDiskObject(filename)) FreeDiskObject(DO); /* Icon found */
else PutDiskObject(filename,&DataIcon); /* if no icon, create one */
}
}
Close(fp);
if (tokenrec) DeleteRecord(&tokenrec);
FreeInput(Pr->CurrentLayout->Window);
UpdateTitleBar(Pr,NULL); /* Maybe a new name? */
return TRUE;
}
void Save(struct Pro *Pr, char SaveMode)
{
/* Called from "Save as..", and the "Output..." submenu */
struct FileRequester *fr;
char fullname[FMSIZE];
BOOL dosave = TRUE;
BOOL filter = FALSE;
int answer;
char *title[5];
char *name;
char *drawer;
title[0] = GetAppStr(MSG_SAVE_AS_ASLREQ_TITLE);
title[1] = GetAppStr(MSG_OUTPUT_VIEW_ASLREQ_TITLE);
title[2] = GetAppStr(MSG_OUTPUT_VIEW_WN_ASLREQ_TITLE);
title[3] = GetAppStr(MSG_OUTPUT_TAB_ASCII_ASLREQ_TITLE);
title[4] = GetAppStr(MSG_OUTPUT_COMMA_ASCII_ASLREQ_TITLE);
if (SaveMode == SAVE_PRO) {
name = Pr->Name;
drawer = Pr->Drawer;
}
else { /* Output menu */
name = Pr->OutputName;
drawer = Pr->OutputDrawer;
if (answer = EasyLocRequest(Pr->CurrentLayout->Window, &ES_Ask_Filtering, NULL, NULL)) {
if (answer == 2) filter = TRUE;
}
else return;
}
/* By supplying the dimension tags to AllocAslRequest, PD programs like */
/* SetASLDim may modify the size to the users preference */
fr = AllocAslRequest(ASL_FileRequest, frtags);
if (AslRequestTags(fr,ASLFR_Window,Pr->CurrentLayout->Window,
ASLFR_SleepWindow,TRUE,
ASLFR_DoSaveMode,TRUE,
ASLFR_TitleText,title[SaveMode],
ASLFR_InitialDrawer, drawer,
ASLFR_InitialFile, name,
TAG_DONE)) {
strcpy(fullname,fr->fr_Drawer);
AddPart(fullname,fr->fr_File,FMSIZE-1);
if (!access(fullname, F_OK)) /* Found a file with the same name */
if (!EasyLocRequest(Pr->CurrentLayout->Window, &ES_SaveWarn, NULL,fr->fr_File)) dosave = FALSE;
if (dosave == TRUE) SavePro(Pr,fr->fr_Drawer,fr->fr_File, SaveMode, filter);
}
FreeAslRequest(fr);
}
struct Pro *LoadPro(char *Drawer, char *Name)
{
struct Pro *npr;
BPTR fp;
char *buf; /* This buffer holds max one field at a time */
char fullname[FMSIZE];
int retval;
UpdateRecord(CurrentPro);
if (CurrentPro->Modified & PROMODIFIED) /* File modified */
if (!EasyLocRequest(CurrentPro->CurrentLayout->Window, &ES_LoadWarn,
NULL, NULL)) return NULL;
strcpy(fullname,Drawer);
if (!AddPart(fullname,Name,FMSIZE-1)) { /* incorrect filename */
/* display error req */
return NULL;
}
if (!(fp = Open(fullname, MODE_OLDFILE))) { /* open fail */
EasyLocRequest(CurrentPro->CurrentLayout->Window,
&ES_OpenFail, NULL, fullname);
return NULL;
}
SetVBuf(fp, NULL, BUF_FULL, MY_FILE_BUF);
/* So far so good. Setup a new project */
if (!(npr = NewPro())) return NULL;
strcpy(npr->Drawer,Drawer);
strcpy(npr->Name,Name);
/* Make a call to RFFParse */
if ((retval = RFFParse(npr,fp)) < 0) {
ShowError(retval,fullname);
Close(fp);
DeletePro(npr);
return NULL;
}
/* Now we waste the old project and make the new project the current one */
DeletePro(CurrentPro);
CurrentPro = npr;
/* Open the window so the user can see the loading */
if ((retval = OpenLayWin(npr, npr->CurrentLayout)) < 0) {
ShowError(retval,fullname);
Close(fp);
DeletePro(CurrentPro);
CurrentPro = NULL;
return NULL;
}
UpdateTitleBar(npr,GetAppStr(MSG_LOADING_WINMSG)); /* User feedback that a file is loading */
BlockInput(CurrentPro->CurrentLayout->Window,TRUE);
/* Do the loading. */
if (!(buf = AllocMem(LOADBUFFERSIZE, MEMF_ANY))) {
Close(fp);
SetProMode(npr,MODE_NORMAL);
FreeInput(CurrentPro->CurrentLayout->Window);
return NULL;
}
while (LoadRecord(fp,buf,npr,npr->CurrentRec)) {
if (!AddRecord(&npr->CurrentRec)) {
/* out of memory */
EasyLocRequest(npr->CurrentLayout->Window, &ES_MemWarn, NULL, NULL);
break;
}
npr->CurrentRec = npr->CurrentRec->Next;
npr->RecSum++;
npr->RecNum++;
}
Close(fp);
FreeMem(buf,LOADBUFFERSIZE);
KillRecord(npr); /* Handles everything except updates */
JumpList(npr,-npr->RecNum); /* Start at top of file */
SetProMode(npr,MODE_NORMAL);
FreeInput(CurrentPro->CurrentLayout->Window);
return npr;
}
BOOL HandleArgs(int argc, char *argv[])
{
/* Handles incoming arguments and open files. Opens only one file for now */
/* Handles ToolTypes and also works from CLI */
/* Uses AmigaDOS ReadArgs which has template support from CLI */
struct WBStartup *argmsg;
struct WBArg *wb_arg;
struct Pro *npr = NULL;
char argdir[FMSIZE]; /* See dos.h */
if (argc == 0) { /* Running from WB */
/* Get filename and drawername of icon to load */
argmsg = (struct WBStartup *)argv;
wb_arg = argmsg->sm_ArgList; /* head of the arg list */
if (argmsg->sm_NumArgs > 1) { /* File(s) exists, load first only */
wb_arg++; /* Skip over main program to first file */
if (NULL != wb_arg->wa_Lock) {
/* locks supported, change to the proper directory */
NameFromLock(wb_arg->wa_Lock,argdir,sizeof(argdir)); /* Path */
npr=LoadPro(argdir,wb_arg->wa_Name);
}
/* else do nothing as that filesystem doesn't support locks */
}
}
else { /* Running from CLI */
/* Handle CLI args */
if (MyArgArray[FILES]) { /* There are at least one file to load */
/* Get argdir */
stcgfp(argdir,*(char **)MyArgArray[FILES]);
npr=LoadPro(argdir,FilePart(*(UBYTE **)MyArgArray[FILES]));
}
}
if (!CurrentPro) ByeBye();
/* If no project was loaded, open empty win */
if (!npr) if (OpenLayWin(CurrentPro, CurrentPro->CurrentLayout) < 0) ByeBye();
UpdateTitleBar(CurrentPro, NULL);
return TRUE;
}
void InitSerial(void)
{
/* Set up serial device */
/* Needs to be done AFTER the ToolTypes has been set by HandleArgs(); */
if (!(SerialMP = CreatePort(0,0))) ByeBye();
if (!(SerialIO = (struct IOExtSer *)
CreateExtIO(SerialMP, sizeof(struct IOExtSer))))
ByeBye();
SerialIO->io_SerFlags = SERF_SHARED; // Turn on shared mode
if (OpenDevice((char *)MyArgArray[DEVICE],*(UBYTE *)MyArgArray[UNIT],
(struct IORequest *)SerialIO,0)) {
EasyLocRequest(CurrentPro->CurrentLayout->Window,
&ES_DialFail, NULL, (char *)MyArgArray[DEVICE],
*(UBYTE *)MyArgArray[UNIT]);
CloseSerial();
}
}
int DoDial(char *phonenumber)
{
char ds[800];
char *dialstring = ds;
extern void __asm DialDTMF(register __a0 char *phonenumber,
register __d0 unsigned int speed);
extern void __asm DialCCITT5(register __a0 char *phonenumber,
register __d0 unsigned int speed);
if (!IsPhoneNumber(phonenumber)) {
DisplayBeep(Scr);
return RC_WARN;
}
/* Fix the eventual areacode stripping */
if(!Strnicmp(phonenumber, (char *)MyArgArray[AREACODE],
strlen((char *)MyArgArray[AREACODE])))
phonenumber += strlen((char *)MyArgArray[AREACODE]);
sprintf(dialstring,"%s%s%s\r",
(char *)MyArgArray[DIALPREFIX],
phonenumber,
(char *)MyArgArray[DIALPOSTFIX]);
if (MyArgArray[TONEDIAL]) {
if (MyArgArray[CCITT5])
DialCCITT5(phonenumber, *(UBYTE *)MyArgArray[TONEDIALSPEED]);
else DialDTMF(phonenumber, *(UBYTE *)MyArgArray[TONEDIALSPEED]);
return RC_OK;
}
/* Init serial device if not initialized before */
if (!SerialMP) InitSerial();
if (!SerialMP) return RC_ERROR;
SerialIO->IOSer.io_Command = CMD_WRITE;
SerialIO->IOSer.io_Length = -1; // Null terminated string
SerialIO->IOSer.io_Data = dialstring;
DoIO((struct IORequest *)SerialIO); // Send data
return RC_OK;
}
void DoSelect(struct Pro *Pr)
{
/* Select records from a ListView with fields */
struct Rec *rec;
Select *s;
BOOL again = TRUE;
struct VisFldInfo *vf = GetVisFldInfo(CurrentPro->CurrentLayout, LastGad);
s = Pr->CurrentLayout->Browser;
if (!s) return; /* safety */
UpdateRecord(Pr);
/* Sort on the selected field first? */
if (DB_Msg.Qualifier & IXSYM_SHIFTMASK) DoSort(Pr, vf->Offset);
if (!FixSelectSize(s, Pr->RecSum)) return; /* For speed */
/* Seek first record */
for (rec = Pr->CurrentRec; rec->Prev; rec = rec->Prev);
BlockInput(Pr->CurrentLayout->Window,TRUE); /* First a sleep clock */
/* Fill the Select object */
if (vf->Gadget->GadgetID == STRING_KIND) /* For sake of speed, CodeToText does this also */
for (; rec; rec = rec->Next) AddStringLast(s, GetFld(rec, vf->Offset));
else /* Cycle- and checkbox gadgets */
for (; rec; rec = rec->Next) AddStringLast(s, CodeToText(vf, GetFld(rec, vf->Offset)));
s->SelIndex = Pr->RecNum;
OpenSelect(s, Pr->CurrentLayout->Window, vf->Name, GetAppStr(MSG_BROWSE_MODE_SCRMSG));
while (again) {
WaitPort(s->SelWnd->UserPort);
switch(HandleSelectIDCMP(s)) {
case SEL_SELECT :
JumpList(Pr, s->SelIndex - Pr->RecNum);
UpdateDragBar(Pr);
UpdateWindow(Pr);
break;
case SEL_OK :
case SEL_CANCEL :
again = FALSE;
break;
case SEL_HELP :
EasyLocRequest(NULL, &ES_BrowseHelp, NULL, NULL);
break;
}
}
FreeInput(Pr->CurrentLayout->Window);
CloseSelect(s);
RemoveAllStrings(s);
}
/*
* Some more security functions
*/
char *stripLF(char *s)
{
char *start;
for (start = s; *s; s++) if (*s == '\n') *s = '\0';
return start;
}
BOOL rightKey(BPTR fp)
/* Security is turned off as the source is released.
* I only ensure that registered users get their name displayed correctly.
*/
{
// char correctPassWord[12];
char userName[50];
char userPassWord[50];
char idBuf[10];
if (FGets(fp, userName, 40) &&
FGets(fp, idBuf, 10) &&
FGets(fp, userPassWord, 40)) {
stripLF(userName);
stripLF(idBuf);
stripLF(userPassWord);
strcpy(UserName, userName);
UserID = atoi(idBuf);
return TRUE;
}
}
BOOL checkKeyFile(void)
{
/* Security is turned off as the source is released.
* I only ensure that registered users get their name displayed correctly.
*/
BPTR fp;
if (((fp = Open("PROGDIR:db.key", MODE_OLDFILE)) ||
(fp = Open("l:db.key", MODE_OLDFILE)) ||
(fp = Open("s:db.key", MODE_OLDFILE))) &&
rightKey(fp)) {
PassWordOk = TRUE;
Close(fp);
return TRUE;
}
if (fp) Close(fp);
return FALSE;
}
/**********************************************************************/
/* Init */
/**********************************************************************/
void Init(int argc, char *argv[])
{
/* First open alla libraries (SAS C 6.5 handles this automatically) */
UBYTE *tooltype;
BPTR lock;
if ((IntuitionBase = (struct IntuitionBase *)
OpenLibrary("intuition.library",37)) == NULL) ByeBye();
if ((GfxBase = (struct GfxBase *)
OpenLibrary("graphics.library",37)) == NULL) ByeBye();
/* For commodities tooltypes, and icon creation */
if ((IconBase = OpenLibrary("icon.library",37)) == NULL) ByeBye();
if ((CxBase = OpenLibrary("commodities.library",37)) == NULL) ByeBye();
if ((AslBase = OpenLibrary("asl.library",37)) == NULL) ByeBye();
if ((GadToolsBase = OpenLibrary("gadtools.library",37)) == NULL) ByeBye();
if (!(UtilityBase = OpenLibrary("utility.library",37))) ByeBye();
if (!(WorkbenchBase = OpenLibrary("workbench.library", 37))) ByeBye();
if (!(IFFParseBase = OpenLibrary("iffparse.library", 37))) ByeBye();
if (TextFieldBase = OpenLibrary(TEXTFIELD_NAME, TEXTFIELD_VER)) {
TextFieldClass = TEXTFIELD_GetClass();
}
RexxSysBase = OpenLibrary(RXSNAME,0L);
/* Do the argument check, and possible fail now */
if(argc == 0) { /* WB */
/* First parse icon's ToolTypes */
TTypes = ArgArrayInit(argc, argv);
if (tooltype = FindToolType(TTypes,"DEVICE"))
MyArgArray[DEVICE] = (LONG)tooltype;
if (tooltype = FindToolType(TTypes,"UNIT"))
*(UBYTE *)MyArgArray[UNIT] = atoi(tooltype);
if (tooltype = FindToolType(TTypes,"DIALPREFIX"))
MyArgArray[DIALPREFIX] = (LONG)tooltype;
if (tooltype = FindToolType(TTypes,"DIALPOSTFIX"))
MyArgArray[DIALPOSTFIX] = (LONG)tooltype;
if (tooltype = FindToolType(TTypes,"AREACODE"))
MyArgArray[AREACODE] = (LONG)tooltype;
if (tooltype = FindToolType(TTypes,"PUBSCREEN"))
MyArgArray[PUBSCREEN] = (LONG)tooltype;
if (tooltype = FindToolType(TTypes,"FONTNAME"))
MyArgArray[FONTNAME] = (LONG)tooltype;
if (tooltype = FindToolType(TTypes,"FONTSIZE"))
*(int *)MyArgArray[FONTSIZE] = atoi(tooltype);
if (tooltype = FindToolType(TTypes,"NOICONS"))
MyArgArray[NOICONS] = TRUE;
if (tooltype = FindToolType(TTypes,"NOSPEEDRENDER"))
MyArgArray[NOSPEEDRENDER] = TRUE;
if (tooltype = FindToolType(TTypes,"NORETURNSTEP"))
MyArgArray[NORETURNSTEP] = TRUE;
if (tooltype = FindToolType(TTypes,"NOSERIAL"))
MyArgArray[NOSERIAL] = TRUE;
if (tooltype = FindToolType(TTypes,"HORIZBAR"))
MyArgArray[HORIZBAR] = TRUE;
if (tooltype = FindToolType(TTypes,"ESCQUIT"))
MyArgArray[ESCQUIT] = TRUE;
if (tooltype = FindToolType(TTypes,"TONEDIAL"))
MyArgArray[TONEDIAL] = TRUE;
if (tooltype = FindToolType(TTypes,"TONEDIALSPEED"))
*(UBYTE *)MyArgArray[TONEDIALSPEED] = atoi(tooltype);
if (tooltype = FindToolType(TTypes,"CCITT5"))
MyArgArray[CCITT5] = TRUE;
if (tooltype = FindToolType(TTypes,"MAKEBACKUP"))
MyArgArray[MAKEBACKUP] = TRUE;
if (tooltype = FindToolType(TTypes,"LOCALESORT"))
MyArgArray[LOCALESORT] = TRUE;
if (tooltype = FindToolType(TTypes,"HIGHLABEL"))
MyArgArray[HIGHLABEL] = TRUE;
if (tooltype = FindToolType(TTypes,"NOBORDER"))
MyArgArray[NOBORDER] = TRUE;
}
else { /* CLI */
if (!(MyRDArgs = ReadArgs(MyTemplate,MyArgArray,NULL))) ByeBye();
}
checkKeyFile(); /* Security */
if (LocaleBase = OpenLibrary("locale.library",38)) {
LocaleInfo.li_LocaleBase = LocaleBase;
LocaleInfo.li_Catalog = OpenCatalog(NULL,"db.catalog",
OC_Version, 3, TAG_DONE);
if (MyArgArray[LOCALESORT] && (MyLocale = OpenLocale(NULL))) {
/* Nothing here yet */
}
}
/* For the Clipboard */
if (!(Iff0 = AllocIFF())) ByeBye();
if (!(Iff0->iff_Stream = (ULONG) OpenClipboard(0))) ByeBye();
InitIFFasClip(Iff0);
if (!(Iff1 = AllocIFF())) ByeBye();
if (!(Iff1->iff_Stream = (ULONG) OpenClipboard(1))) ByeBye();
InitIFFasClip(Iff1);
/* Get programname and path for correct 'default tool' in icons */
if (lock = GetProgramDir()) NameFromLock(lock, ProgramDirAndName,FMSIZE);
AddPart(ProgramDirAndName,"db",FMSIZE);
DataIcon.do_DefaultTool = ProgramDirAndName;
if (SetupScreen()) ByeBye(); /* GadToolBox */
if ((AWPort = CreateMsgPort()) == NULL) ByeBye(); /* AppWindow */
if (RexxSysBase) if ((MyRexxPort = SetupRexxPort("DB")) == NULL) ByeBye();
/* Get the users custom font */
if (*(int *)MyArgArray[FONTSIZE] != -1) { /* User wants a custom font */
if (!(DiskfontBase = OpenLibrary("diskfont.library", 37))) ByeBye();
UserTextAttr.ta_Name = (STRPTR)MyArgArray[FONTNAME];
UserTextAttr.ta_YSize = *(int *)MyArgArray[FONTSIZE];
UserTextFont = OpenDiskFont(&UserTextAttr);
}
/* Create one project and layout */
if (!(CurrentPro = NewPro())) ByeBye();
if (!NewLayout(CurrentPro)) ByeBye();
HandleArgs(argc, argv); /* Read arguments (CLI/WB) and open window and file */
}
/**********************************************************************/
/* Eventhandlers that GadToolBox calls directly */
/**********************************************************************/
void VisFldSelected(struct Gadget *gad)
{
CurrentPro->Modified |= RECMODIFIED;
/* Update the Rexx current field offset now */
CurrentPro->CurrentFldOffset = GetVisFldInfo(CurrentPro->CurrentLayout, gad)->Offset;
}
void DragGadgetSelected(void)
{
switch (CurrentPro->Mode) {
case MODE_NORMAL:
UpdateRecord(CurrentPro);
JumpList(CurrentPro,DB_Msg.Code - CurrentPro->RecNum);
UpdateDragBar(CurrentPro); /* This "snaps" the dragbar correctly */
UpdateWindow(CurrentPro);
break;
case MODE_FIND:
case MODE_SORT:
break;
}
}
void DoKill(BOOL ask)
{
/* If ask is FALSE then no questions will be asked, (used by DB_CUT) */
struct Layout *lay = CurrentPro->CurrentLayout;
struct VisFldInfo *vf=lay->FirstVisFldInfo;
BOOL empty = TRUE;
switch (CurrentPro->Mode) {
case MODE_NORMAL:
for (; vf; vf = vf->Next) if (strlen(ReadVisFld(CurrentPro, vf))) empty = FALSE;
if (!empty) if (DisplayWarnings && ask)
if (!EasyLocRequest(CurrentPro->CurrentLayout->Window,
&ES_KillWarn, NULL, NULL)) break;
if (KillRecord(CurrentPro) == TRUE) {
UpdateDragBar(CurrentPro);
UpdateWindow(CurrentPro);
CurrentPro->Modified |= PROMODIFIED;
}
else DisplayBeep(Scr);
break;
case MODE_FIND:
/* Just clear the fields */
ClearRecord(CurrentPro->FindRec);
UpdateGadgets(CurrentPro);
break;
case MODE_SORT:
ClearRecord(CurrentPro->SortRec); /* InitSortRecord(CurrentPro); */
UpdateGadgets(CurrentPro);
break;
}
}
int DB_KILL( void )
{
/* routine when (sub)item "Kill" is selected. */
DoKill(TRUE);
return 0;
}
int DB_NEW( void )
{
/* routine when (sub)item "New" is selected. */
UpdateRecord(CurrentPro);
if (CurrentPro->Modified & PROMODIFIED) /* File modified */
if (!EasyLocRequest(CurrentPro->CurrentLayout->Window, &ES_NewWarn, NULL, NULL)) return 0;
if (ClearPro(CurrentPro) == FALSE) ByeBye();
strcpy(CurrentPro->Name,GetAppStr(MSG_UNTITLED_PRO));
/* We save the current drawer as the user will probably want that */
UpdateDragBar(CurrentPro);
UpdateWindow(CurrentPro);
return 0;
}
int DB_OPEN( void )
{
/* routine when (sub)item "Open..." is selected. */
struct FileRequester *fr;
/* NewPro will be called which in turn calls SetProMode so we don't have to */
/* By supplying the dimension tags to AllocAslRequest, PD programs like */
/* SetASLDim may modify the size to the users preference */
fr = AllocAslRequest(ASL_FileRequest, frtags);
if (AslRequestTags(fr,ASLFR_Window,CurrentPro->CurrentLayout->Window,
ASLFR_SleepWindow, TRUE,
ASLFR_TitleText,GetAppStr(MSG_OPEN_ASLREQ_TITLE),
ASLFR_InitialDrawer, CurrentPro->Drawer,
ASLFR_InitialFile, CurrentPro->Name,
TAG_DONE)) LoadPro(fr->fr_Drawer,fr->fr_File);
FreeAslRequest(fr);
if (!CurrentPro) ByeBye();
return 1; /* Old window closed, GadToolBox must ignore extra menuevents */
}
int DB_SAVEAS( void )
{
/* routine when (sub)item "Save as..." is selected. */
Save(CurrentPro,SAVE_PRO);
return 0;
}
int DB_SAVE( void )
{
/* routine when (sub)item "Save" is selected. */
{
if (Stricmp(CurrentPro->Name,GetAppStr(MSG_UNTITLED_PRO))) /* File saved before */
SavePro(CurrentPro,CurrentPro->Drawer,CurrentPro->Name,SAVE_PRO, FALSE);
else DB_SAVEAS();
}
return 0;
}
int DB_OUTPUT_VIEW( void )
{
/* routine when (sub)item "Output view..." is selected. */
Save(CurrentPro,SAVE_VIEW);
return 0;
}
int DB_OUTPUT_VIEW_WN( void )
{
/* routine when (sub)item "Output view with names..." is selected. */
Save(CurrentPro,SAVE_VIEW_WN);
return 0;
}
int DB_OUTPUT_TAB_ASCII( void )
{
/* routine when (sub)item "Output Tab ASCII..." is selected. */
Save(CurrentPro,SAVE_TAB_ASCII);
return 0;
}
int DB_OUTPUT_COMMA_ASCII( void )
{
/* routine when (sub)item "Output Comma ASCII..." is selected. */
Save(CurrentPro,SAVE_COMMA_ASCII);
return 0;
}
int DB_ABOUT( void )
{
/* routine when (sub)item "About..." is selected. */
if (!EasyLocRequest(CurrentPro->CurrentLayout->Window, &ES_About, NULL,
&Version[9], MyRexxPortName, UserName, UserID))
if (!EasyLocRequest(CurrentPro->CurrentLayout->Window, &ES_MoreAbout, NULL, NULL))
EasyLocRequest(CurrentPro->CurrentLayout->Window, &ES_MH_RFF, NULL, NULL);
return 0;
}
int DB_QUIT( void )
{
/* routine when (sub)item "Quit" is selected. */
HandleQuit(CurrentPro);
return 0;
}
int DB_COPY( void )
{
/* routine when (sub)item "Copy" is selected. */
UpdateRecord(CurrentPro);
if (!CopyToClipboard(CurrentPro)) DisplayBeep(Scr);
return 0;
}
int DB_CUT( void )
{
/* routine when (sub)item "Cut" is selected. */
DB_COPY();
DoKill(FALSE);
return 0;
}
int DB_PASTE( void )
{
/* routine when (sub)item "Paste" is selected. */
struct Rec *rp, *crp;
switch (CurrentPro->Mode) {
case MODE_NORMAL:
if (!(rp = NewRecord())) {
EasyLocRequest(CurrentPro->CurrentLayout->Window, &ES_MemWarn, NULL, NULL);
break;
}
if (!PasteFromClipboard(CurrentPro, rp)) {
DeleteRecord(&rp);
break;
}
/* Everything ok, now link it */
crp = CurrentPro->CurrentRec;
rp->Next = crp->Next; /* Curr New->Next */
crp->Next = rp; /* Curr->New Next */
rp->Prev = crp; /* Curr<-New Next */
if (rp->Next) rp->Next->Prev = rp; /* Curr New<-Next */
UpdateRecord(CurrentPro);
CurrentPro->CurrentRec = CurrentPro->CurrentRec->Next;
CurrentPro->RecSum++;
CurrentPro->RecNum++;
UpdateDragBar(CurrentPro);
UpdateWindow(CurrentPro);
CurrentPro->Modified |= PROMODIFIED;
break;
case MODE_FIND:
PasteFromClipboard(CurrentPro, CurrentPro->FindRec);
UpdateGadgets(CurrentPro);
break;
case MODE_SORT:
PasteFromClipboard(CurrentPro, CurrentPro->SortRec);
UpdateGadgets(CurrentPro);
break;
}
return 0;
}
__inline static BOOL OkStrGad(struct Gadget *g) /* Duplicate from dbGUI.c */
{
return (BOOL)(g->Flags & GFLG_TABCYCLE && !(g->Flags & GFLG_DISABLED));
}
int DB_ADD( void )
{
struct VisFldInfo *vf;
/* routine when (sub)item "Add" is selected. */
switch (CurrentPro->Mode) {
case MODE_NORMAL:
if (AddRecord(&CurrentPro->CurrentRec)) {
UpdateRecord(CurrentPro);
CurrentPro->CurrentRec = CurrentPro->CurrentRec->Next;
CurrentPro->RecSum++;
CurrentPro->RecNum++;
UpdateDragBar(CurrentPro);
UpdateWindow(CurrentPro);
for (vf = CurrentPro->CurrentLayout->FirstVisFldInfo; vf; vf = vf->Next) {
if (OkStrGad(vf->Gadget)) {
LastGad = vf->Gadget;
VisFldSelected(vf->Gadget);
ActivateGadget(vf->Gadget, CurrentPro->CurrentLayout->Window, NULL);
break;
}
}
}
else EasyLocRequest(CurrentPro->CurrentLayout->Window, &ES_MemWarn, NULL, NULL);
break;
}
return 0;
}
int LayIndex(struct Layout *first, struct Layout *current)
{
int i;
for (i=0; first && first != current; first = first->NextLayout, i++);
return i;
}
int ChangeView(struct Layout *lay)
{
/* This new version is a "hack". If there are problems, use older versions */
/* If lay is NULL, use the menu instead (ARexx reason) */
/* routine when one of the "View" items are selected. */
/* We check if the menuitem really is checked first. */
/* (User may play around with both mousebuttons, activating */
/* menuitems without checking them.) */
struct MenuItem *m;
struct Layout *oldlay;
int retval, viewnum;
WORD ww, wh;
oldlay = CurrentPro->CurrentLayout;
if (!lay) {
m = ItemAddress(CurrentPro->Menu, DB_Msg.Code);
if (!(m->Flags & CHECKED)) return 0;
viewnum = ITEMNUM(DB_Msg.Code);
for (lay = CurrentPro->FirstLayout; viewnum; viewnum--, lay = lay->NextLayout);
}
else {
m = ItemAddress(CurrentPro->Menu, FULLMENUNUM(2, LayIndex(CurrentPro->FirstLayout, oldlay), NOSUB));
m->Flags &= ~CHECKED; /* Delete old checkmark */
m = ItemAddress(CurrentPro->Menu, FULLMENUNUM(2, LayIndex(CurrentPro->FirstLayout, lay), NOSUB));
m->Flags |= CHECKED; /* Set new checkmark */
}
UpdateRecord(CurrentPro);
if (!lay || (lay==oldlay)) return 0;
DeleteAllGadgets(oldlay, USE_MODE);
CurrentPro->CurrentLayout = lay;
lay->Window = oldlay->Window; /* We use the same window now */
lay->AppWin = oldlay->AppWin;
oldlay->Window = NULL;
oldlay->AppWin = NULL;
if ((retval = CalcAllPos(CurrentPro, CurrentPro->CurrentLayout, &ww, &wh)) < 0) {
ShowError(retval,NULL);
/* Try to fall back to the old layout */
CurrentPro->CurrentLayout = oldlay;
oldlay->Window = lay->Window; /* We use the same window now */
oldlay->AppWin = lay->AppWin; /* We use the same window now */
lay->Window = NULL;
lay->AppWin = NULL;
/* Correct the checkmark so it indicates this window */
m->Flags &= ~CHECKED; /* Delete old checkmark */
m = ItemAddress(CurrentPro->Menu, FULLMENUNUM(2, LayIndex(CurrentPro->FirstLayout, oldlay), NOSUB));
m->Flags |= CHECKED; /* Set new checkmark */
if ((retval = CalcAllPos(CurrentPro, CurrentPro->CurrentLayout, &ww, &wh)) < 0) {
ShowError(retval,NULL);
ByeBye();
}
}
CreateAllGadgets(CurrentPro, CurrentPro->CurrentLayout, ww, wh, USE_MODE);
AttachAllGadgets(CurrentPro->CurrentLayout, ww, wh, USE_MODE);
UpdateWindow(CurrentPro);
UpdateDragBar(CurrentPro);
return 0;
}
int DB_VIEW() {
return ChangeView(NULL);
}
/*
int DB_VIEW( void )
{
/* routine when one of the "View" items are selected. */
/* We check if the menuitem really is checked first. */
/* (User may play around with both mousebuttons, activating */
/* menuitems without checking them.) */
struct MenuItem *m;
struct Layout *lay, *oldlay;
int i,pronum,retval;
oldlay = CurrentPro->CurrentLayout;
m = ItemAddress(CurrentPro->Menu, DB_Msg.Code);
if (!(m->Flags & CHECKED)) return 0;
UpdateRecord(CurrentPro);
pronum = ITEMNUM(DB_Msg.Code);
for (lay=CurrentPro->FirstLayout,i=0; lay && (i<pronum); lay=lay->NextLayout, i++);
if (!lay || (lay==oldlay)) return 0;
CloseLayWin(CurrentPro, oldlay);
CurrentPro->CurrentLayout = lay;
if ((retval = OpenLayWin(CurrentPro, CurrentPro->CurrentLayout)) < 0) {
ShowError(retval,NULL);
/* Try to fall back to the old layout */
CurrentPro->CurrentLayout = oldlay;
/* Correct the checkmark so it indicates this window */
for (lay=CurrentPro->FirstLayout,i=0; lay != oldlay; lay=lay->NextLayout, i++);
m->Flags &= ~CHECKED; /* Delete old checkmark */
m = ItemAddress(CurrentPro->Menu, FULLMENUNUM(2,i,NOSUB));
m->Flags |= CHECKED; /* Set new checkmark */
if ((retval = OpenLayWin(CurrentPro, CurrentPro->CurrentLayout)) < 0) {
ShowError(retval,NULL);
ByeBye();
}
}
UpdateWindow(CurrentPro);
UpdateDragBar(CurrentPro);
return 1; /* The old window is closed, so don't access more items */
}
*/
int DB_FIND( void )
{
/* routine when (sub)item "Find..." is selected. */
// UpdateRecord(CurrentPro); /* We are going to leave this record */
SetProMode(CurrentPro,MODE_FIND);
return 0;
}
int DB_FINDNEXT( void )
{
/* routine when (sub)item "Find next" is selected. */
if (CurrentPro->Mode != MODE_SORT)
FindRecord(CurrentPro,CurrentPro->RecNum+1,1);
return 0;
}
int DB_SORT( void )
{
/* routine when (sub)item "Sort" is selected. */
// UpdateRecord(CurrentPro); /* We are going to leave this record */
SetProMode(CurrentPro,MODE_SORT);
return 0;
}
int DB_DIAL( void )
{
/* routine when (sub)item "Dial" is selected. */
DoDial(ReadVisFld(CurrentPro, GetVisFldInfo(CurrentPro->CurrentLayout, LastGad)));
return 0;
}
int DB_BROWSE( void )
{
/* routine when (sub)item "Browse..." is selected. */
if (LastGad) DoSelect(CurrentPro);
else DisplayBeep(Scr);
return 0;
}
int DB_WARNINGS( void )
{
/* routine when (sub)item "Display warnings" is selected. */
struct MenuItem *m;
m = ItemAddress(CurrentPro->CurrentLayout->Window->MenuStrip, DB_Msg.Code);
if (m->Flags & CHECKED) DisplayWarnings = TRUE;
else DisplayWarnings = FALSE;
return 0;
}
int DB_AZ( void )
{
/* routine when (sub)item "A-Z" is selected. */
/* We check if the menuitem really is checked first. */
/* (User may play around with both mousebuttons on the menus, activating */
/* menuitems without checking them.) */
struct MenuItem *m;
m = ItemAddress(CurrentPro->CurrentLayout->Window->MenuStrip, DB_Msg.Code);
if (m->Flags & CHECKED) SI.SortDir = SORT_DIR_AZ;
return 0;
}
int DB_ZA( void )
{
/* routine when (sub)item "Z-A" is selected. */
/* We check if the menuitem really is checked first. */
/* (User may play around with both mousebuttons on the menus, activating */
/* menuitems without checking them.) */
struct MenuItem *m;
m = ItemAddress(CurrentPro->CurrentLayout->Window->MenuStrip, DB_Msg.Code);
if (m->Flags & CHECKED) SI.SortDir = SORT_DIR_ZA;
return 0;
}
/*
int DB_SAVESETTINGS( void )
{
/* routine when (sub)item "Save settings..." is selected. */
return 0;
}
*/
int DB_FIELD_DEFINITION( void )
{
/* routine when (sub)item "Field definition" is selected. */
return 0;
}
int DB_VIEW_DESIGN( void )
{
/* routine when (sub)item "View design" is selected. */
UpdateRecord(CurrentPro);
Design(CurrentPro, CurrentPro->CurrentLayout);
return 1; /* Window has been closed and a new has been opened */
}
int DB_EXECUTE_AREXX( void )
{
/* routine when (sub)item "Execute ARexx script..." is selected. */
struct FileRequester *fr;
char fullname[FMSIZE];
BOOL error = FALSE;
if (!MyRexxPort) {
DisplayBeep(Scr);
return 0;
}
/* By supplying the dimension tags to AllocAslRequest, PD programs like */
/* SetASLDim may modify the size to the users preference */
fr = AllocAslRequest(ASL_FileRequest, frtags);
if (AslRequestTags(fr,ASLFR_Window,CurrentPro->CurrentLayout->Window,
ASLFR_SleepWindow, TRUE,
ASLFR_TitleText,GetAppStr(MSG_EXECUTE_AREXX_ASLREQ_TITLE),
ASLFR_InitialDrawer, CurrentPro->ARexxDrawer,
ASLFR_InitialFile, CurrentPro->ARexxName,
TAG_DONE)) {
strcpy(fullname, fr->fr_Drawer);
if (!AddPart(fullname, fr->fr_File, FMSIZE-1)) error = TRUE; /* incorrect filename */
}
else error = TRUE;
strcpy(CurrentPro->ARexxDrawer, fr->fr_Drawer);
strcpy(CurrentPro->ARexxName,fr->fr_File);
FreeAslRequest(fr);
if (!error) SendRexxCommand(fullname);
return 0;
}
void DoARexxMenu(int num)
{
/* Execute an ARexx script on the menu. */
int i;
struct RxInfo *ri;
struct RFFTag *tag;
for (ri=CurrentPro->FirstRxInfo,i=0; ri && (i<num); ri=ri->Next, i++);
if (ri && (tag = FindTag(&ri->RxTags, RXSTRING)))
SendRexxStrCommand(tag->Data);
else if (ri && (tag = FindTag(&ri->RxTags, RXFILE)))
SendRexxCommand(tag->Data);
}
int DB_AREXX( void )
{
/* routine when an item in the ARexx menu is selected. */
int num;
num = ITEMNUM(DB_Msg.Code) - 1;
DoARexxMenu(num);
return 0;
}
int DB_NewSize( void )
{
/* routine for "IDCMP_NEWSIZE". */
if (MyArgArray[NOBORDER]) return 0;
SpeedRenderOff(CurrentPro->CurrentLayout);
if (CurrentPro->CurrentLayout->FirstVisFldInfo)
RefreshGList(CurrentPro->CurrentLayout->FirstVisFldInfo->Gadget, CurrentPro->CurrentLayout->Window, NULL, -1);
if (!(SpeedRenderOn(CurrentPro->CurrentLayout))) ByeBye();
return 0;
}
int DB_CloseWindow( void )
{
/* routine for "IDCMP_CLOSEWINDOW". */
switch (CurrentPro->Mode) {
case MODE_NORMAL:
HandleQuit(CurrentPro);
break;
case MODE_FIND: /* Abort find mode */
case MODE_SORT: /* Abort sort mode */
// UpdateRecord(CurrentPro);
SetProMode(CurrentPro,MODE_NORMAL);
break;
}
return 0;
}
int DB_MenuHelp( void )
{
/* routine for "IDCMP_MENUHELP". */
struct EasyStruct *HelpText = &ES_MH_NoHelp;
USHORT menuNum, itemNum, subNum;
menuNum = MENUNUM(DB_Msg.Code);
itemNum = ITEMNUM(DB_Msg.Code);
subNum = SUBNUM(DB_Msg.Code);
switch (menuNum) {
case 0: /* Project Menu */
switch (itemNum) {
case NOITEM: break;
case 0:
HelpText = &ES_MH_New;
break;
case 1:
case 3:
case 4: HelpText = &ES_MH_RFF; break;
case 5:
switch (subNum) {
case NOSUB: break;
case 0: HelpText = &ES_MH_Output_View; break;
case 1: HelpText = &ES_MH_Output_View_WN; break;
case 2: HelpText = &ES_MH_tab_ASCII; break;
case 3: HelpText = &ES_MH_comma_ASCII; break;
}
break;
}
break;
case 1: /* Edit Menu */
switch (itemNum) {
case NOITEM: break;
case 0:
case 1:
case 2: HelpText = &ES_MH_Clip; break;
case 6: HelpText = &ES_MH_Kill; break;
}
break;
case 2: /* View Menu */
break;
case 3: /* Action Menu */
switch (itemNum) {
case NOITEM: break;
case 0:
case 1: HelpText = &ES_FindHelp; break;
case 3: HelpText = &ES_SortHelp; break;
case 4: HelpText = &ES_DialHelp; break;
case 5: HelpText = &ES_BrowseHelp; break;
}
break;
case 4: /* Settings Menu */
switch (itemNum) {
case NOITEM: break;
case 0: HelpText = &ES_MH_Warnings; break;
case 1:
switch (subNum) {
case NOSUB: HelpText = &ES_MH_SortDir; break;
case 0: HelpText = &ES_MH_SortDir; break;
case 1: HelpText = &ES_MH_SortDir; break;
}
break;
case 3: HelpText = &ES_MH_Field_Definition; break;
case 4: HelpText = &ES_MH_View_Design; break;
}
break;
case 5: /* ARexx menu */
HelpText = &ES_MH_ARexx; break;
break;
case NOMENU: /* No menu selected, can happen with IDCMP_MENUHELP */
break;
}
EasyLocRequest(CurrentPro->CurrentLayout->Window, HelpText, NULL, NULL);
return 0;
}
int DB_SpecialAction(BOOL async)
{
/* Routine called when user doubleclicks a stringgadget or hits LAMIGA+Key */
LONG rxfiletagID, rxstrtagID;
struct RFFTag *rxtag;
BOOL success;
if (!MyRexxPort || (CurrentPro->Mode != MODE_NORMAL)) return 0;
if (!async) { /* ie also use the AUTORX tags */
rxfiletagID = AUTORXFILE;
rxstrtagID = AUTORXSTRING;
}
else {
rxfiletagID = RXFILE;
rxstrtagID = RXSTRING;
}
if (rxtag = SearchTags(CurrentPro, NULL, NULL, rxstrtagID, rxfiletagID))
if (rxtag->ID == rxstrtagID) success = SendRexxStrCommand(rxtag->Data);
else success = SendRexxCommand(rxtag->Data);
else if (async)
DoSelect(CurrentPro); /* Select records from a ListView with fields */
if (async) return 0;
else if (success) {
do WaitPort(MyRexxPort);
while (!HandleRexxMessage(MyRexxPort));
}
return 0;
}
int DB_VanillaKey( void )
{
/* routine for "IDCMP_VANILLAKEY". */
struct VisFldInfo *vf;
char shortcut, *cursor;
switch (DB_Msg.Code) {
case '\r' :
switch (CurrentPro->Mode) {
case MODE_FIND: /* Start find */
FindRecord(CurrentPro,0,1);
break;
case MODE_SORT: /* Start sort */
DoSort(CurrentPro, NORMAL_SORT);
break;
case MODE_NORMAL: /* Find next */
if (DB_Msg.Qualifier & IXSYM_SHIFTMASK) {
FindRecord(CurrentPro,CurrentPro->RecNum-1,-1);
} else FindRecord(CurrentPro,CurrentPro->RecNum+1,1);
break;
}
break;
case VANILLA_ESC :
switch (CurrentPro->Mode) {
case MODE_NORMAL:
if (MyArgArray[ESCQUIT]) HandleQuit(CurrentPro);
break;
case MODE_FIND: /* Abort find mode */
case MODE_SORT: /* Abort sort mode */
// UpdateRecord(CurrentPro);
SetProMode(CurrentPro,MODE_NORMAL);
break;
}
break;
case VANILLA_DEL :
break;
case '\t' :
if (CurrentPro->CurrentLayout->FirstVisFldInfo)
ActivateGadget(LastGad, CurrentPro->CurrentLayout->Window, NULL);
break;
case ' ' : /* A fast way to switch to search mode and clear the fields */
// UpdateRecord(CurrentPro);
SetProMode(CurrentPro,MODE_FIND);
DoKill(TRUE);
break;
default : /* Key-activation of gadgets or SpecialAction() */
for (vf = CurrentPro->CurrentLayout->FirstVisFldInfo; vf; vf = vf->Next) {
for (shortcut = '\0', cursor = vf->Name; *cursor; cursor++) {
if (*cursor == '_') {
shortcut = *(cursor+1);
break;
}
}
if (ToUpper(DB_Msg.Code) == ToUpper(shortcut)) {
if (DB_Msg.Qualifier & IEQUALIFIER_LCOMMAND) {
LastGad = vf->Gadget;
CurrentPro->CurrentFldOffset = vf->Offset;
DB_SpecialAction(TRUE);
}
else MyActivateGadget(vf, CurrentPro->CurrentLayout->Window);
break;
}
}
break;
}
return 0;
}
int DB_RawKey( void )
{
/* routine for "IDCMP_RAWKEY". */
/* dirty fix for HORIZBAR */
if (MyArgArray[HORIZBAR]) {
switch (DB_Msg.Code) {
case RAW_LEFT : DB_Msg.Code = RAW_UP; break;
case RAW_RIGHT : DB_Msg.Code = RAW_DOWN; break;
}
}
switch (DB_Msg.Code) {
case RAW_UP :
switch (CurrentPro->Mode) {
case MODE_NORMAL:
if (CurrentPro->RecNum > 0) {
UpdateRecord(CurrentPro);
if (DB_Msg.Qualifier & IXSYM_SHIFTMASK) {
JumpList(CurrentPro,-CurrentPro->RecNum);
}
else JumpList(CurrentPro, -1);
UpdateDragBar(CurrentPro);
UpdateWindow(CurrentPro);
}
if (ReactivateGad)
ActivateGadget(LastGad, CurrentPro->CurrentLayout->Window, NULL);
break;
}
break;
case RAW_DOWN:
switch (CurrentPro->Mode) {
case MODE_NORMAL:
if (CurrentPro->RecNum < (CurrentPro->RecSum-1)) {
UpdateRecord(CurrentPro);
if (DB_Msg.Qualifier & IXSYM_SHIFTMASK) {
JumpList(CurrentPro,CurrentPro->RecSum-CurrentPro->RecNum-1);
}
else JumpList(CurrentPro, 1);
UpdateDragBar(CurrentPro);
UpdateWindow(CurrentPro);
}
if (ReactivateGad)
ActivateGadget(LastGad, CurrentPro->CurrentLayout->Window, NULL);
break;
}
break;
case RAW_TAB:
ActivateGadget(LastGad, CurrentPro->CurrentLayout->Window, NULL);
break;
case RAW_HELP:
switch (CurrentPro->Mode) {
case MODE_NORMAL:
EasyLocRequest(CurrentPro->CurrentLayout->Window, &ES_NormalHelp, NULL, NULL);
break;
case MODE_FIND:
EasyLocRequest(CurrentPro->CurrentLayout->Window, &ES_FindHelp, NULL, NULL);
break;
case MODE_SORT:
EasyLocRequest(CurrentPro->CurrentLayout->Window, &ES_SortHelp, NULL, NULL);
break;
}
}
if (DB_Msg.Code >= RAW_F1 && DB_Msg.Code <= RAW_F10)
DoARexxMenu(DB_Msg.Code - RAW_F1 + 1);
return 0;
}
int DB_MouseButtons( void )
{
/* routine for "IDCMP_MOUSEBUTTONS". */
return 0;
}
/**********************************************************************/
/* Eventhandlers that GadToolBox won't supply code for */
/**********************************************************************/
int DB_MouseMove( void )
{
/* Dragregeln rapporterar sitt läge i DB_Msg.Code */
switch (CurrentPro->Mode) {
case MODE_NORMAL:
UpdateRecord(CurrentPro);
JumpList(CurrentPro,DB_Msg.Code-CurrentPro->RecNum);
UpdateWindow(CurrentPro);
break;
case MODE_FIND:
break;
}
return 0;
}
void HandleAppWindow(void)
/* This only loads one of possibly many shift-dropped icon files */
{
struct AppMessage *AppMsg;
struct WBArg *wb_arg;
char argdir[FMSIZE];
while (AppMsg = (struct AppMessage *) GetMsg(AWPort)) {
wb_arg = AppMsg->am_ArgList;
if (AppMsg->am_NumArgs > 0) { /* At least one file */
if (wb_arg->wa_Lock) {
/* locks supported, change to the proper directory */
NameFromLock(wb_arg->wa_Lock,argdir,sizeof(argdir)); /* Path */
LoadPro(argdir,wb_arg->wa_Name);
}
}
ReplyMsg((struct Message *) AppMsg);
if (!CurrentPro) ByeBye();
}
/* It's nice to have the window activated also */
ActivateWindow(CurrentPro->CurrentLayout->Window);
}
/**********************************************************************/
/* main */
/**********************************************************************/
void main(int argc, char *argv[])
{
ULONG appwinsig, myrexxportsig=0, signals;
Init(argc, argv); /* Open libraries and windows.. */
appwinsig = 1L << AWPort->mp_SigBit;
if (MyRexxPort) myrexxportsig = 1L << MyRexxPort->mp_SigBit;
/* Handle IDCMP events */
for (;;) {
/* GadToolBox won't wait */
signals = Wait(WinSig | appwinsig | myrexxportsig);
if (signals & WinSig) {
/* This function in turn calls almost all functions.. */
/* Note IDCMP_MOUSEMOVE case has to be added, se top of code */
HandleDB_IDCMP(CurrentPro->CurrentLayout);
switch ( DB_Msg.Class ) {
case IDCMP_REFRESHWINDOW:
SpeedRenderOff(CurrentPro->CurrentLayout);
UpdateGadgets(CurrentPro);
if (!(SpeedRenderOn(CurrentPro->CurrentLayout))) ByeBye();
break;
}
}
if (signals & appwinsig) {
HandleAppWindow();
}
if (signals & myrexxportsig)
HandleRexxMessage(MyRexxPort);
}
}